package msgpack import ( "encoding" "errors" "fmt" "reflect" ) var ( interfaceType = reflect.TypeOf((*interface{})(nil)).Elem() stringType = reflect.TypeOf((*string)(nil)).Elem() boolType = reflect.TypeOf((*bool)(nil)).Elem() ) var valueDecoders []decoderFunc //nolint:gochecknoinits func init() { valueDecoders = []decoderFunc{ reflect.Bool: decodeBoolValue, reflect.Int: decodeInt64Value, reflect.Int8: decodeInt64Value, reflect.Int16: decodeInt64Value, reflect.Int32: decodeInt64Value, reflect.Int64: decodeInt64Value, reflect.Uint: decodeUint64Value, reflect.Uint8: decodeUint64Value, reflect.Uint16: decodeUint64Value, reflect.Uint32: decodeUint64Value, reflect.Uint64: decodeUint64Value, reflect.Float32: decodeFloat32Value, reflect.Float64: decodeFloat64Value, reflect.Complex64: decodeUnsupportedValue, reflect.Complex128: decodeUnsupportedValue, reflect.Array: decodeArrayValue, reflect.Chan: decodeUnsupportedValue, reflect.Func: decodeUnsupportedValue, reflect.Interface: decodeInterfaceValue, reflect.Map: decodeMapValue, reflect.Ptr: decodeUnsupportedValue, reflect.Slice: decodeSliceValue, reflect.String: decodeStringValue, reflect.Struct: decodeStructValue, reflect.UnsafePointer: decodeUnsupportedValue, } } func getDecoder(typ reflect.Type) decoderFunc { if v, ok := typeDecMap.Load(typ); ok { return v.(decoderFunc) } fn := _getDecoder(typ) typeDecMap.Store(typ, fn) return fn } func _getDecoder(typ reflect.Type) decoderFunc { kind := typ.Kind() if kind == reflect.Ptr { if _, ok := typeDecMap.Load(typ.Elem()); ok { return ptrValueDecoder(typ) } } if typ.Implements(customDecoderType) { return nilAwareDecoder(typ, decodeCustomValue) } if typ.Implements(unmarshalerType) { return nilAwareDecoder(typ, unmarshalValue) } if typ.Implements(binaryUnmarshalerType) { return nilAwareDecoder(typ, unmarshalBinaryValue) } if typ.Implements(textUnmarshalerType) { return nilAwareDecoder(typ, unmarshalTextValue) } // Addressable struct field value. if kind != reflect.Ptr { ptr := reflect.PtrTo(typ) if ptr.Implements(customDecoderType) { return addrDecoder(nilAwareDecoder(typ, decodeCustomValue)) } if ptr.Implements(unmarshalerType) { return addrDecoder(nilAwareDecoder(typ, unmarshalValue)) } if ptr.Implements(binaryUnmarshalerType) { return addrDecoder(nilAwareDecoder(typ, unmarshalBinaryValue)) } if ptr.Implements(textUnmarshalerType) { return addrDecoder(nilAwareDecoder(typ, unmarshalTextValue)) } } switch kind { case reflect.Ptr: return ptrValueDecoder(typ) case reflect.Slice: elem := typ.Elem() if elem.Kind() == reflect.Uint8 { return decodeBytesValue } if elem == stringType { return decodeStringSliceValue } case reflect.Array: if typ.Elem().Kind() == reflect.Uint8 { return decodeByteArrayValue } case reflect.Map: if typ.Key() == stringType { switch typ.Elem() { case stringType: return decodeMapStringStringValue case interfaceType: return decodeMapStringInterfaceValue } } } return valueDecoders[kind] } func ptrValueDecoder(typ reflect.Type) decoderFunc { decoder := getDecoder(typ.Elem()) return func(d *Decoder, v reflect.Value) error { if d.hasNilCode() { if !v.IsNil() { v.Set(d.newValue(typ).Elem()) } return d.DecodeNil() } if v.IsNil() { v.Set(d.newValue(typ.Elem())) } return decoder(d, v.Elem()) } } func addrDecoder(fn decoderFunc) decoderFunc { return func(d *Decoder, v reflect.Value) error { if !v.CanAddr() { return fmt.Errorf("msgpack: Decode(nonaddressable %T)", v.Interface()) } return fn(d, v.Addr()) } } func nilAwareDecoder(typ reflect.Type, fn decoderFunc) decoderFunc { if nilable(typ.Kind()) { return func(d *Decoder, v reflect.Value) error { if d.hasNilCode() { return d.decodeNilValue(v) } if v.IsNil() { v.Set(d.newValue(typ.Elem())) } return fn(d, v) } } return func(d *Decoder, v reflect.Value) error { if d.hasNilCode() { return d.decodeNilValue(v) } return fn(d, v) } } func decodeBoolValue(d *Decoder, v reflect.Value) error { flag, err := d.DecodeBool() if err != nil { return err } v.SetBool(flag) return nil } func decodeInterfaceValue(d *Decoder, v reflect.Value) error { if v.IsNil() { return d.interfaceValue(v) } return d.DecodeValue(v.Elem()) } func (d *Decoder) interfaceValue(v reflect.Value) error { vv, err := d.decodeInterfaceCond() if err != nil { return err } if vv != nil { if v.Type() == errorType { if vv, ok := vv.(string); ok { v.Set(reflect.ValueOf(errors.New(vv))) return nil } } v.Set(reflect.ValueOf(vv)) } return nil } func decodeUnsupportedValue(d *Decoder, v reflect.Value) error { return fmt.Errorf("msgpack: Decode(unsupported %s)", v.Type()) } //------------------------------------------------------------------------------ func decodeCustomValue(d *Decoder, v reflect.Value) error { decoder := v.Interface().(CustomDecoder) return decoder.DecodeMsgpack(d) } func unmarshalValue(d *Decoder, v reflect.Value) error { var b []byte d.rec = make([]byte, 0, 64) if err := d.Skip(); err != nil { return err } b = d.rec d.rec = nil unmarshaler := v.Interface().(Unmarshaler) return unmarshaler.UnmarshalMsgpack(b) } func unmarshalBinaryValue(d *Decoder, v reflect.Value) error { data, err := d.DecodeBytes() if err != nil { return err } unmarshaler := v.Interface().(encoding.BinaryUnmarshaler) return unmarshaler.UnmarshalBinary(data) } func unmarshalTextValue(d *Decoder, v reflect.Value) error { data, err := d.DecodeBytes() if err != nil { return err } unmarshaler := v.Interface().(encoding.TextUnmarshaler) return unmarshaler.UnmarshalText(data) }