github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/market/contact.go (about) 1 /* 2 * Copyright (C) 2017 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package market 19 20 import "encoding/json" 21 22 // ContactList is list of Contact structures, to have custom JSON marshaling 23 type ContactList []Contact 24 25 // MarshalJSON encodes in such manner that `null` situation avoided in JSON 26 func (list ContactList) MarshalJSON() ([]byte, error) { 27 if list == nil { 28 return json.Marshal([]Contact{}) 29 } 30 return json.Marshal([]Contact(list)) 31 } 32 33 // Contact represents contact object with type and concrete definition according to type 34 type Contact struct { 35 Type string `json:"type"` 36 Definition ContactDefinition `json:"definition"` 37 } 38 39 // ContactDefinition is interface for contacts of all types 40 type ContactDefinition interface { 41 } 42 43 // UnsupportedContactType is a contact which is returned by unserializer when encountering unregistered types of contact 44 type UnsupportedContactType struct { 45 } 46 47 var _ ContactDefinition = UnsupportedContactType{} 48 49 // ContactDefinitionUnserializer represents function which called for concrete contact type to unserialize 50 type ContactDefinitionUnserializer func(*json.RawMessage) (ContactDefinition, error) 51 52 // contact unserializer registry 53 // TODO avoid global map variables and wrap this functionality into some kind of component? 54 var contactDefinitionMap = make(map[string]ContactDefinitionUnserializer) 55 56 // RegisterContactUnserializer registers unserializer for specified contact type. 57 func RegisterContactUnserializer(contactType string, unserializer func(*json.RawMessage) (ContactDefinition, error)) { 58 contactDefinitionMap[contactType] = unserializer 59 } 60 61 func unserializeContacts(message *json.RawMessage) (contactList ContactList) { 62 contactList = ContactList{} 63 if message == nil { 64 return 65 } 66 67 // get an array of raw definitions 68 var contacts []struct { 69 Type string `json:"type"` 70 Definition *json.RawMessage `json:"definition"` 71 } 72 if err := json.Unmarshal([]byte(*message), &contacts); err != nil { 73 return 74 } 75 76 for _, contactItem := range contacts { 77 contactList = append(contactList, Contact{ 78 Type: contactItem.Type, 79 Definition: unserializeContact(contactItem.Type, contactItem.Definition), 80 }) 81 } 82 83 return 84 } 85 86 func unserializeContact(contactType string, rawMessage *json.RawMessage) ContactDefinition { 87 fn, ok := contactDefinitionMap[contactType] 88 if !ok { 89 return UnsupportedContactType{} 90 } 91 definition, err := fn(rawMessage) 92 if err != nil { 93 return UnsupportedContactType{} 94 } 95 96 return definition 97 }