168 lines
4 KiB
Go
168 lines
4 KiB
Go
package msgpack
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
var valueEncoders []encoderFunc
|
|
|
|
func init() {
|
|
valueEncoders = []encoderFunc{
|
|
reflect.Bool: encodeBoolValue,
|
|
reflect.Int: encodeInt64Value,
|
|
reflect.Int8: encodeInt64Value,
|
|
reflect.Int16: encodeInt64Value,
|
|
reflect.Int32: encodeInt64Value,
|
|
reflect.Int64: encodeInt64Value,
|
|
reflect.Uint: encodeUint64Value,
|
|
reflect.Uint8: encodeUint64Value,
|
|
reflect.Uint16: encodeUint64Value,
|
|
reflect.Uint32: encodeUint64Value,
|
|
reflect.Uint64: encodeUint64Value,
|
|
reflect.Float32: encodeFloat32Value,
|
|
reflect.Float64: encodeFloat64Value,
|
|
reflect.Complex64: encodeUnsupportedValue,
|
|
reflect.Complex128: encodeUnsupportedValue,
|
|
reflect.Array: encodeArrayValue,
|
|
reflect.Chan: encodeUnsupportedValue,
|
|
reflect.Func: encodeUnsupportedValue,
|
|
reflect.Interface: encodeInterfaceValue,
|
|
reflect.Map: encodeMapValue,
|
|
reflect.Ptr: encodeUnsupportedValue,
|
|
reflect.Slice: encodeSliceValue,
|
|
reflect.String: encodeStringValue,
|
|
reflect.Struct: encodeStructValue,
|
|
reflect.UnsafePointer: encodeUnsupportedValue,
|
|
}
|
|
}
|
|
|
|
func getEncoder(typ reflect.Type) encoderFunc {
|
|
if encoder, ok := typEncMap[typ]; ok {
|
|
return encoder
|
|
}
|
|
|
|
if typ.Implements(customEncoderType) {
|
|
return encodeCustomValue
|
|
}
|
|
if typ.Implements(marshalerType) {
|
|
return marshalValue
|
|
}
|
|
|
|
kind := typ.Kind()
|
|
|
|
// Addressable struct field value.
|
|
if kind != reflect.Ptr {
|
|
ptr := reflect.PtrTo(typ)
|
|
if ptr.Implements(customEncoderType) {
|
|
return encodeCustomValuePtr
|
|
}
|
|
if ptr.Implements(marshalerType) {
|
|
return marshalValuePtr
|
|
}
|
|
}
|
|
|
|
if typ == errorType {
|
|
return encodeErrorValue
|
|
}
|
|
|
|
switch kind {
|
|
case reflect.Ptr:
|
|
return ptrEncoderFunc(typ)
|
|
case reflect.Slice:
|
|
if typ.Elem().Kind() == reflect.Uint8 {
|
|
return encodeByteSliceValue
|
|
}
|
|
case reflect.Array:
|
|
if typ.Elem().Kind() == reflect.Uint8 {
|
|
return encodeByteArrayValue
|
|
}
|
|
case reflect.Map:
|
|
if typ.Key() == stringType {
|
|
switch typ.Elem() {
|
|
case stringType:
|
|
return encodeMapStringStringValue
|
|
case interfaceType:
|
|
return encodeMapStringInterfaceValue
|
|
}
|
|
}
|
|
}
|
|
return valueEncoders[kind]
|
|
}
|
|
|
|
func ptrEncoderFunc(typ reflect.Type) encoderFunc {
|
|
encoder := getEncoder(typ.Elem())
|
|
return func(e *Encoder, v reflect.Value) error {
|
|
if v.IsNil() {
|
|
return e.EncodeNil()
|
|
}
|
|
return encoder(e, v.Elem())
|
|
}
|
|
}
|
|
|
|
func encodeCustomValuePtr(e *Encoder, v reflect.Value) error {
|
|
if !v.CanAddr() {
|
|
return fmt.Errorf("msgpack: Encode(non-addressable %T)", v.Interface())
|
|
}
|
|
encoder := v.Addr().Interface().(CustomEncoder)
|
|
return encoder.EncodeMsgpack(e)
|
|
}
|
|
|
|
func encodeCustomValue(e *Encoder, v reflect.Value) error {
|
|
switch v.Kind() {
|
|
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
|
|
if v.IsNil() {
|
|
return e.EncodeNil()
|
|
}
|
|
}
|
|
|
|
encoder := v.Interface().(CustomEncoder)
|
|
return encoder.EncodeMsgpack(e)
|
|
}
|
|
|
|
func marshalValuePtr(e *Encoder, v reflect.Value) error {
|
|
if !v.CanAddr() {
|
|
return fmt.Errorf("msgpack: Encode(non-addressable %T)", v.Interface())
|
|
}
|
|
return marshalValue(e, v.Addr())
|
|
}
|
|
|
|
func marshalValue(e *Encoder, v reflect.Value) error {
|
|
switch v.Kind() {
|
|
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
|
|
if v.IsNil() {
|
|
return e.EncodeNil()
|
|
}
|
|
}
|
|
|
|
marshaler := v.Interface().(Marshaler)
|
|
b, err := marshaler.MarshalMsgpack()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = e.w.Write(b)
|
|
return err
|
|
}
|
|
|
|
func encodeBoolValue(e *Encoder, v reflect.Value) error {
|
|
return e.EncodeBool(v.Bool())
|
|
}
|
|
|
|
func encodeInterfaceValue(e *Encoder, v reflect.Value) error {
|
|
if v.IsNil() {
|
|
return e.EncodeNil()
|
|
}
|
|
return e.EncodeValue(v.Elem())
|
|
}
|
|
|
|
func encodeErrorValue(e *Encoder, v reflect.Value) error {
|
|
if v.IsNil() {
|
|
return e.EncodeNil()
|
|
}
|
|
return e.EncodeString(v.Interface().(error).Error())
|
|
}
|
|
|
|
func encodeUnsupportedValue(e *Encoder, v reflect.Value) error {
|
|
return fmt.Errorf("msgpack: Encode(unsupported %s)", v.Type())
|
|
}
|