8 var errorType = reflect.TypeOf((*error)(nil)).Elem()
10 var customEncoderType = reflect.TypeOf((*CustomEncoder)(nil)).Elem()
11 var customDecoderType = reflect.TypeOf((*CustomDecoder)(nil)).Elem()
13 var marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
14 var unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
16 type encoderFunc func(*Encoder, reflect.Value) error
17 type decoderFunc func(*Decoder, reflect.Value) error
19 var typEncMap = make(map[reflect.Type]encoderFunc)
20 var typDecMap = make(map[reflect.Type]decoderFunc)
22 // Register registers encoder and decoder functions for a value.
23 // This is low level API and in most cases you should prefer implementing
24 // Marshaler/CustomEncoder and Unmarshaler/CustomDecoder interfaces.
25 func Register(value interface{}, enc encoderFunc, dec decoderFunc) {
26 typ := reflect.TypeOf(value)
35 //------------------------------------------------------------------------------
37 var structs = newStructCache(false)
38 var jsonStructs = newStructCache(true)
40 type structCache struct {
42 m map[reflect.Type]*fields
47 func newStructCache(useJSONTag bool) *structCache {
49 m: make(map[reflect.Type]*fields),
51 useJSONTag: useJSONTag,
55 func (m *structCache) Fields(typ reflect.Type) *fields {
66 fs = getFields(typ, m.useJSONTag)
74 //------------------------------------------------------------------------------
84 func (f *field) value(v reflect.Value) reflect.Value {
85 return fieldByIndex(v, f.index)
88 func (f *field) Omit(strct reflect.Value) bool {
89 return f.omitEmpty && isEmptyValue(f.value(strct))
92 func (f *field) EncodeValue(e *Encoder, strct reflect.Value) error {
93 return f.encoder(e, f.value(strct))
96 func (f *field) DecodeValue(d *Decoder, strct reflect.Value) error {
97 return f.decoder(d, f.value(strct))
100 //------------------------------------------------------------------------------
103 Table map[string]*field
110 func newFields(numField int) *fields {
112 Table: make(map[string]*field, numField),
113 List: make([]*field, 0, numField),
117 func (fs *fields) Add(field *field) {
118 fs.Table[field.name] = field
119 fs.List = append(fs.List, field)
121 fs.hasOmitEmpty = true
125 func (fs *fields) OmitEmpty(strct reflect.Value) []*field {
126 if !fs.hasOmitEmpty {
130 fields := make([]*field, 0, len(fs.List))
131 for _, f := range fs.List {
133 fields = append(fields, f)
139 func getFields(typ reflect.Type, useJSONTag bool) *fields {
140 numField := typ.NumField()
141 fs := newFields(numField)
144 for i := 0; i < numField; i++ {
147 tag := f.Tag.Get("msgpack")
148 if useJSONTag && tag == "" {
149 tag = f.Tag.Get("json")
152 name, opt := parseTag(tag)
157 if f.Name == "_msgpack" {
158 if opt.Contains("asArray") {
161 if opt.Contains("omitempty") {
166 if f.PkgPath != "" && !f.Anonymous {
173 omitEmpty: omitEmpty || opt.Contains("omitempty"),
174 encoder: getEncoder(f.Type),
175 decoder: getDecoder(f.Type),
178 if field.name == "" {
182 if f.Anonymous && !opt.Contains("noinline") {
183 inline := opt.Contains("inline")
185 inlineFields(fs, f.Type, field, useJSONTag)
187 inline = autoinlineFields(fs, f.Type, field, useJSONTag)
190 fs.Table[field.name] = field
200 var encodeStructValuePtr uintptr
201 var decodeStructValuePtr uintptr
204 encodeStructValuePtr = reflect.ValueOf(encodeStructValue).Pointer()
205 decodeStructValuePtr = reflect.ValueOf(decodeStructValue).Pointer()
208 func inlineFields(fs *fields, typ reflect.Type, f *field, useJSONTag bool) {
209 inlinedFields := getFields(typ, useJSONTag).List
210 for _, field := range inlinedFields {
211 if _, ok := fs.Table[field.name]; ok {
212 // Don't inline shadowed fields.
215 field.index = append(f.index, field.index...)
220 func autoinlineFields(fs *fields, typ reflect.Type, f *field, useJSONTag bool) bool {
221 var encoder encoderFunc
222 var decoder decoderFunc
224 if typ.Kind() == reflect.Struct {
228 for typ.Kind() == reflect.Ptr {
230 encoder = getEncoder(typ)
231 decoder = getDecoder(typ)
233 if typ.Kind() != reflect.Struct {
238 if reflect.ValueOf(encoder).Pointer() != encodeStructValuePtr {
241 if reflect.ValueOf(decoder).Pointer() != decodeStructValuePtr {
245 inlinedFields := getFields(typ, useJSONTag).List
246 for _, field := range inlinedFields {
247 if _, ok := fs.Table[field.name]; ok {
248 // Don't auto inline if there are shadowed fields.
253 for _, field := range inlinedFields {
254 field.index = append(f.index, field.index...)
260 func isEmptyValue(v reflect.Value) bool {
262 case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
266 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
268 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
270 case reflect.Float32, reflect.Float64:
271 return v.Float() == 0
272 case reflect.Interface, reflect.Ptr:
278 func fieldByIndex(v reflect.Value, index []int) reflect.Value {
280 return v.Field(index[0])
282 for i, x := range index {
285 v, ok = indirectNew(v)
295 func indirectNew(v reflect.Value) (reflect.Value, bool) {
296 if v.Kind() == reflect.Ptr {
301 elemType := v.Type().Elem()
302 if elemType.Kind() != reflect.Struct {
305 v.Set(reflect.New(elemType))