go-libp2p-core/record/record.go
2020-01-17 10:42:26 -05:00

65 lines
1.4 KiB
Go

package record
import (
"errors"
"reflect"
)
var ErrPayloadTypeNotRegistered = errors.New("payload type is not registered")
var payloadTypeRegistry = make(map[string]Record)
type Record interface {
MarshalRecord() ([]byte, error)
UnmarshalRecord([]byte) error
}
func RegisterPayloadType(payloadType []byte, prototype Record) {
payloadTypeRegistry[string(payloadType)] = prototype
}
func unmarshalRecordPayload(payloadType []byte, payloadBytes []byte) (Record, error) {
rec, err := blankRecordForPayloadType(payloadType)
if err != nil {
return nil, err
}
err = rec.UnmarshalRecord(payloadBytes)
if err != nil {
return nil, err
}
return rec, nil
}
func blankRecordForPayloadType(payloadType []byte) (Record, error) {
prototype, ok := payloadTypeRegistry[string(payloadType)]
if !ok {
return nil, ErrPayloadTypeNotRegistered
}
valueType := getValueType(prototype)
val := reflect.New(valueType)
asRecord := val.Interface().(Record)
return asRecord, nil
}
func payloadTypeForRecord(rec Record) ([]byte, bool) {
valueType := getValueType(rec)
for k, v := range payloadTypeRegistry {
t := getValueType(v)
if t.AssignableTo(valueType) {
return []byte(k), true
}
}
return []byte{}, false
}
func getValueType(i interface{}) reflect.Type {
valueType := reflect.TypeOf(i)
if valueType.Kind() == reflect.Ptr {
valueType = valueType.Elem()
}
return valueType
}