package msgpack import ( "errors" "fmt" "reflect" "github.com/vmihailenco/msgpack/codes" ) var interfaceType = reflect.TypeOf((*interface{})(nil)).Elem() var stringType = reflect.TypeOf((*string)(nil)).Elem() var valueDecoders []decoderFunc 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 mustSet(v reflect.Value) error { if !v.CanSet() { return fmt.Errorf("msgpack: Decode(nonsettable %s)", v.Type()) } return nil } func getDecoder(typ reflect.Type) decoderFunc { kind := typ.Kind() if decoder, ok := typDecMap[typ]; ok { return decoder } if typ.Implements(customDecoderType) { return decodeCustomValue } if typ.Implements(unmarshalerType) { return unmarshalValue } // Addressable struct field value. if kind != reflect.Ptr { ptr := reflect.PtrTo(typ) if ptr.Implements(customDecoderType) { return decodeCustomValueAddr } if ptr.Implements(unmarshalerType) { return unmarshalValueAddr } } switch kind { case reflect.Ptr: return ptrDecoderFunc(typ) case reflect.Slice: elem := typ.Elem() switch elem.Kind() { case reflect.Uint8: return decodeBytesValue } switch elem { case 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 ptrDecoderFunc(typ reflect.Type) decoderFunc { decoder := getDecoder(typ.Elem()) return func(d *Decoder, v reflect.Value) error { if d.hasNilCode() { if err := mustSet(v); err != nil { return err } v.Set(reflect.Zero(v.Type())) return d.DecodeNil() } if v.IsNil() { if err := mustSet(v); err != nil { return err } v.Set(reflect.New(v.Type().Elem())) } return decoder(d, v.Elem()) } } func decodeCustomValueAddr(d *Decoder, v reflect.Value) error { if !v.CanAddr() { return fmt.Errorf("msgpack: Decode(nonaddressable %T)", v.Interface()) } return decodeCustomValue(d, v.Addr()) } func decodeCustomValue(d *Decoder, v reflect.Value) error { c, err := d.PeekCode() if err != nil { return err } if codes.IsExt(c) { c, err = d.readCode() if err != nil { return err } extLen, err := d.parseExtLen(c) if err != nil { return err } _, err = d.readCode() if err != nil { return err } c, err = d.PeekCode() if err != nil { return err } d.extLen = extLen } if c == codes.Nil { return d.decodeNilValue(v) } if v.IsNil() { v.Set(reflect.New(v.Type().Elem())) } decoder := v.Interface().(CustomDecoder) return decoder.DecodeMsgpack(d) } func unmarshalValueAddr(d *Decoder, v reflect.Value) error { if !v.CanAddr() { return fmt.Errorf("msgpack: Decode(nonaddressable %T)", v.Interface()) } return unmarshalValue(d, v.Addr()) } func unmarshalValue(d *Decoder, v reflect.Value) error { c, err := d.PeekCode() if err != nil { return err } extLen := d.extLen d.extLen = 0 if extLen == 0 && codes.IsExt(c) { c, err = d.readCode() if err != nil { return err } extLen, err = d.parseExtLen(c) if err != nil { return err } _, err = d.readCode() if err != nil { return err } c, err = d.PeekCode() if err != nil { return err } } if c == codes.Nil { return d.decodeNilValue(v) } if v.IsNil() { v.Set(reflect.New(v.Type().Elem())) } if extLen != 0 { b, err := d.readN(extLen) if err != nil { return err } d.rec = b } else { d.rec = makeBuffer() if err := d.Skip(); err != nil { return err } } unmarshaler := v.Interface().(Unmarshaler) err = unmarshaler.UnmarshalMsgpack(d.rec) d.rec = nil return err } func decodeBoolValue(d *Decoder, v reflect.Value) error { flag, err := d.DecodeBool() if err != nil { return err } if err = mustSet(v); err != nil { return err } v.SetBool(flag) return nil } func decodeInterfaceValue(d *Decoder, v reflect.Value) error { if v.IsNil() { return d.interfaceValue(v) } elem := v.Elem() if !elem.CanAddr() { if d.hasNilCode() { v.Set(reflect.Zero(v.Type())) return d.DecodeNil() } } return d.DecodeValue(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()) }