encode_value.go (5934B)
1 package msgpack 2 3 import ( 4 "encoding" 5 "fmt" 6 "reflect" 7 ) 8 9 var valueEncoders []encoderFunc 10 11 //nolint:gochecknoinits 12 func init() { 13 valueEncoders = []encoderFunc{ 14 reflect.Bool: encodeBoolValue, 15 reflect.Int: encodeIntValue, 16 reflect.Int8: encodeInt8CondValue, 17 reflect.Int16: encodeInt16CondValue, 18 reflect.Int32: encodeInt32CondValue, 19 reflect.Int64: encodeInt64CondValue, 20 reflect.Uint: encodeUintValue, 21 reflect.Uint8: encodeUint8CondValue, 22 reflect.Uint16: encodeUint16CondValue, 23 reflect.Uint32: encodeUint32CondValue, 24 reflect.Uint64: encodeUint64CondValue, 25 reflect.Float32: encodeFloat32Value, 26 reflect.Float64: encodeFloat64Value, 27 reflect.Complex64: encodeUnsupportedValue, 28 reflect.Complex128: encodeUnsupportedValue, 29 reflect.Array: encodeArrayValue, 30 reflect.Chan: encodeUnsupportedValue, 31 reflect.Func: encodeUnsupportedValue, 32 reflect.Interface: encodeInterfaceValue, 33 reflect.Map: encodeMapValue, 34 reflect.Ptr: encodeUnsupportedValue, 35 reflect.Slice: encodeSliceValue, 36 reflect.String: encodeStringValue, 37 reflect.Struct: encodeStructValue, 38 reflect.UnsafePointer: encodeUnsupportedValue, 39 } 40 } 41 42 func getEncoder(typ reflect.Type) encoderFunc { 43 if v, ok := typeEncMap.Load(typ); ok { 44 return v.(encoderFunc) 45 } 46 fn := _getEncoder(typ) 47 typeEncMap.Store(typ, fn) 48 return fn 49 } 50 51 func _getEncoder(typ reflect.Type) encoderFunc { 52 kind := typ.Kind() 53 54 if kind == reflect.Ptr { 55 if _, ok := typeEncMap.Load(typ.Elem()); ok { 56 return ptrEncoderFunc(typ) 57 } 58 } 59 60 if typ.Implements(customEncoderType) { 61 return encodeCustomValue 62 } 63 if typ.Implements(marshalerType) { 64 return marshalValue 65 } 66 if typ.Implements(binaryMarshalerType) { 67 return marshalBinaryValue 68 } 69 if typ.Implements(textMarshalerType) { 70 return marshalTextValue 71 } 72 73 // Addressable struct field value. 74 if kind != reflect.Ptr { 75 ptr := reflect.PtrTo(typ) 76 if ptr.Implements(customEncoderType) { 77 return encodeCustomValuePtr 78 } 79 if ptr.Implements(marshalerType) { 80 return marshalValuePtr 81 } 82 if ptr.Implements(binaryMarshalerType) { 83 return marshalBinaryValueAddr 84 } 85 if ptr.Implements(textMarshalerType) { 86 return marshalTextValueAddr 87 } 88 } 89 90 if typ == errorType { 91 return encodeErrorValue 92 } 93 94 switch kind { 95 case reflect.Ptr: 96 return ptrEncoderFunc(typ) 97 case reflect.Slice: 98 elem := typ.Elem() 99 if elem.Kind() == reflect.Uint8 { 100 return encodeByteSliceValue 101 } 102 if elem == stringType { 103 return encodeStringSliceValue 104 } 105 case reflect.Array: 106 if typ.Elem().Kind() == reflect.Uint8 { 107 return encodeByteArrayValue 108 } 109 case reflect.Map: 110 if typ.Key() == stringType { 111 switch typ.Elem() { 112 case stringType: 113 return encodeMapStringStringValue 114 case interfaceType: 115 return encodeMapStringInterfaceValue 116 } 117 } 118 } 119 120 return valueEncoders[kind] 121 } 122 123 func ptrEncoderFunc(typ reflect.Type) encoderFunc { 124 encoder := getEncoder(typ.Elem()) 125 return func(e *Encoder, v reflect.Value) error { 126 if v.IsNil() { 127 return e.EncodeNil() 128 } 129 return encoder(e, v.Elem()) 130 } 131 } 132 133 func encodeCustomValuePtr(e *Encoder, v reflect.Value) error { 134 if !v.CanAddr() { 135 return fmt.Errorf("msgpack: Encode(non-addressable %T)", v.Interface()) 136 } 137 encoder := v.Addr().Interface().(CustomEncoder) 138 return encoder.EncodeMsgpack(e) 139 } 140 141 func encodeCustomValue(e *Encoder, v reflect.Value) error { 142 if nilable(v.Kind()) && v.IsNil() { 143 return e.EncodeNil() 144 } 145 146 encoder := v.Interface().(CustomEncoder) 147 return encoder.EncodeMsgpack(e) 148 } 149 150 func marshalValuePtr(e *Encoder, v reflect.Value) error { 151 if !v.CanAddr() { 152 return fmt.Errorf("msgpack: Encode(non-addressable %T)", v.Interface()) 153 } 154 return marshalValue(e, v.Addr()) 155 } 156 157 func marshalValue(e *Encoder, v reflect.Value) error { 158 if nilable(v.Kind()) && v.IsNil() { 159 return e.EncodeNil() 160 } 161 162 marshaler := v.Interface().(Marshaler) 163 b, err := marshaler.MarshalMsgpack() 164 if err != nil { 165 return err 166 } 167 _, err = e.w.Write(b) 168 return err 169 } 170 171 func encodeBoolValue(e *Encoder, v reflect.Value) error { 172 return e.EncodeBool(v.Bool()) 173 } 174 175 func encodeInterfaceValue(e *Encoder, v reflect.Value) error { 176 if v.IsNil() { 177 return e.EncodeNil() 178 } 179 return e.EncodeValue(v.Elem()) 180 } 181 182 func encodeErrorValue(e *Encoder, v reflect.Value) error { 183 if v.IsNil() { 184 return e.EncodeNil() 185 } 186 return e.EncodeString(v.Interface().(error).Error()) 187 } 188 189 func encodeUnsupportedValue(e *Encoder, v reflect.Value) error { 190 return fmt.Errorf("msgpack: Encode(unsupported %s)", v.Type()) 191 } 192 193 func nilable(kind reflect.Kind) bool { 194 switch kind { 195 case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: 196 return true 197 } 198 return false 199 } 200 201 //------------------------------------------------------------------------------ 202 203 func marshalBinaryValueAddr(e *Encoder, v reflect.Value) error { 204 if !v.CanAddr() { 205 return fmt.Errorf("msgpack: Encode(non-addressable %T)", v.Interface()) 206 } 207 return marshalBinaryValue(e, v.Addr()) 208 } 209 210 func marshalBinaryValue(e *Encoder, v reflect.Value) error { 211 if nilable(v.Kind()) && v.IsNil() { 212 return e.EncodeNil() 213 } 214 215 marshaler := v.Interface().(encoding.BinaryMarshaler) 216 data, err := marshaler.MarshalBinary() 217 if err != nil { 218 return err 219 } 220 221 return e.EncodeBytes(data) 222 } 223 224 //------------------------------------------------------------------------------ 225 226 func marshalTextValueAddr(e *Encoder, v reflect.Value) error { 227 if !v.CanAddr() { 228 return fmt.Errorf("msgpack: Encode(non-addressable %T)", v.Interface()) 229 } 230 return marshalTextValue(e, v.Addr()) 231 } 232 233 func marshalTextValue(e *Encoder, v reflect.Value) error { 234 if nilable(v.Kind()) && v.IsNil() { 235 return e.EncodeNil() 236 } 237 238 marshaler := v.Interface().(encoding.TextMarshaler) 239 data, err := marshaler.MarshalText() 240 if err != nil { 241 return err 242 } 243 244 return e.EncodeBytes(data) 245 }