|
|
@@ -8,48 +8,102 @@ import (
|
|
|
)
|
|
|
|
|
|
func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
|
|
|
- fieldsByToName := map[string]int{}
|
|
|
- orderedFields := []*structFieldTo{}
|
|
|
+ type bindingTo struct {
|
|
|
+ binding *Binding
|
|
|
+ toName string
|
|
|
+ ignored bool
|
|
|
+ }
|
|
|
+ orderedBindings := []*bindingTo{}
|
|
|
structDescriptor, err := describeStruct(cfg, typ)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
- for index, binding := range structDescriptor.Fields {
|
|
|
+ for _, binding := range structDescriptor.Fields {
|
|
|
for _, toName := range binding.ToNames {
|
|
|
- oldIndex, found := fieldsByToName[toName]
|
|
|
- if found {
|
|
|
- orderedFields[oldIndex] = nil // replaced by the later one
|
|
|
+ new := &bindingTo{
|
|
|
+ binding: binding,
|
|
|
+ toName: toName,
|
|
|
}
|
|
|
- fieldsByToName[toName] = index
|
|
|
- orderedFields = append(orderedFields, &structFieldTo{
|
|
|
- binding.Encoder.(*structFieldEncoder),
|
|
|
- toName,
|
|
|
- })
|
|
|
+ for _, old := range orderedBindings {
|
|
|
+ if old.toName != toName {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ old.ignored, new.ignored = resolveConflictBinding(old.binding, new.binding)
|
|
|
+ }
|
|
|
+ orderedBindings = append(orderedBindings, new)
|
|
|
}
|
|
|
}
|
|
|
- if len(orderedFields) == 0 {
|
|
|
+ if len(orderedBindings) == 0 {
|
|
|
return &emptyStructEncoder{}, nil
|
|
|
}
|
|
|
finalOrderedFields := []structFieldTo{}
|
|
|
- for _, structFieldTo := range orderedFields {
|
|
|
- if structFieldTo != nil {
|
|
|
- finalOrderedFields = append(finalOrderedFields, *structFieldTo)
|
|
|
+ for _, bindingTo := range orderedBindings {
|
|
|
+ if !bindingTo.ignored {
|
|
|
+ finalOrderedFields = append(finalOrderedFields, structFieldTo{
|
|
|
+ encoder: bindingTo.binding.Encoder.(*structFieldEncoder),
|
|
|
+ toName: bindingTo.toName,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return &structEncoder{structDescriptor.onePtrEmbedded, structDescriptor.onePtrOptimization, finalOrderedFields}, nil
|
|
|
+}
|
|
|
+
|
|
|
+func resolveConflictBinding(old, new *Binding) (ignoreOld, ignoreNew bool) {
|
|
|
+ newTagged := new.Field.Tag.Get("json") != ""
|
|
|
+ oldTagged := old.Field.Tag.Get("json") != ""
|
|
|
+ if newTagged {
|
|
|
+ if oldTagged {
|
|
|
+ if len(old.levels) > len(new.levels) {
|
|
|
+ return true, false
|
|
|
+ } else if len(new.levels) > len(old.levels) {
|
|
|
+ return false, true
|
|
|
+ } else {
|
|
|
+ return true, true
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return true, false
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if oldTagged {
|
|
|
+ return true, false
|
|
|
+ } else {
|
|
|
+ if len(old.levels) > len(new.levels) {
|
|
|
+ return true, false
|
|
|
+ } else if len(new.levels) > len(old.levels) {
|
|
|
+ return false, true
|
|
|
+ } else {
|
|
|
+ return true, true
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- return &structEncoder{structDescriptor.onePtrEmbedded,structDescriptor.onePtrOptimization,finalOrderedFields}, nil
|
|
|
}
|
|
|
|
|
|
func decoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
|
|
|
- fields := map[string]*structFieldDecoder{}
|
|
|
+ bindings := map[string]*Binding{}
|
|
|
structDescriptor, err := describeStruct(cfg, typ)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
for _, binding := range structDescriptor.Fields {
|
|
|
for _, fromName := range binding.FromNames {
|
|
|
- fields[fromName] = binding.Decoder.(*structFieldDecoder)
|
|
|
+ old := bindings[fromName]
|
|
|
+ if old == nil {
|
|
|
+ bindings[fromName] = binding
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ ignoreOld, ignoreNew := resolveConflictBinding(old, binding)
|
|
|
+ if ignoreOld {
|
|
|
+ delete(bindings, fromName)
|
|
|
+ }
|
|
|
+ if !ignoreNew {
|
|
|
+ bindings[fromName] = binding
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+ fields := map[string]*structFieldDecoder{}
|
|
|
+ for k, binding := range bindings {
|
|
|
+ fields[k] = binding.Decoder.(*structFieldDecoder)
|
|
|
+ }
|
|
|
return createStructDecoder(typ, fields)
|
|
|
}
|
|
|
|
|
|
@@ -120,7 +174,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
|
|
}
|
|
|
}
|
|
|
return &threeFieldsStructDecoder{typ,
|
|
|
- fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil
|
|
|
+ fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil
|
|
|
case 4:
|
|
|
var fieldName1 int32
|
|
|
var fieldName2 int32
|
|
|
@@ -153,8 +207,8 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
|
|
}
|
|
|
}
|
|
|
return &fourFieldsStructDecoder{typ,
|
|
|
- fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
|
|
- fieldName4, fieldDecoder4}, nil
|
|
|
+ fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
|
|
+ fieldName4, fieldDecoder4}, nil
|
|
|
case 5:
|
|
|
var fieldName1 int32
|
|
|
var fieldName2 int32
|
|
|
@@ -192,8 +246,8 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
|
|
}
|
|
|
}
|
|
|
return &fiveFieldsStructDecoder{typ,
|
|
|
- fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
|
|
- fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil
|
|
|
+ fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
|
|
+ fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil
|
|
|
case 6:
|
|
|
var fieldName1 int32
|
|
|
var fieldName2 int32
|
|
|
@@ -236,8 +290,8 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
|
|
}
|
|
|
}
|
|
|
return &sixFieldsStructDecoder{typ,
|
|
|
- fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
|
|
- fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil
|
|
|
+ fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
|
|
+ fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil
|
|
|
case 7:
|
|
|
var fieldName1 int32
|
|
|
var fieldName2 int32
|
|
|
@@ -285,9 +339,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
|
|
}
|
|
|
}
|
|
|
return &sevenFieldsStructDecoder{typ,
|
|
|
- fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
|
|
- fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
|
|
- fieldName7, fieldDecoder7}, nil
|
|
|
+ fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
|
|
+ fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
|
|
+ fieldName7, fieldDecoder7}, nil
|
|
|
case 8:
|
|
|
var fieldName1 int32
|
|
|
var fieldName2 int32
|
|
|
@@ -340,9 +394,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
|
|
}
|
|
|
}
|
|
|
return &eightFieldsStructDecoder{typ,
|
|
|
- fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
|
|
- fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
|
|
- fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil
|
|
|
+ fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
|
|
+ fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
|
|
+ fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil
|
|
|
case 9:
|
|
|
var fieldName1 int32
|
|
|
var fieldName2 int32
|
|
|
@@ -400,9 +454,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
|
|
}
|
|
|
}
|
|
|
return &nineFieldsStructDecoder{typ,
|
|
|
- fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
|
|
- fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
|
|
- fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil
|
|
|
+ fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
|
|
+ fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
|
|
+ fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil
|
|
|
case 10:
|
|
|
var fieldName1 int32
|
|
|
var fieldName2 int32
|
|
|
@@ -465,10 +519,10 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
|
|
}
|
|
|
}
|
|
|
return &tenFieldsStructDecoder{typ,
|
|
|
- fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
|
|
- fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
|
|
- fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9,
|
|
|
- fieldName10, fieldDecoder10}, nil
|
|
|
+ fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
|
|
+ fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
|
|
+ fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9,
|
|
|
+ fieldName10, fieldDecoder10}, nil
|
|
|
}
|
|
|
return &generalStructDecoder{typ, fields}, nil
|
|
|
}
|
|
|
@@ -992,9 +1046,9 @@ func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
|
|
}
|
|
|
|
|
|
type structEncoder struct {
|
|
|
- onePtrEmbedded bool
|
|
|
+ onePtrEmbedded bool
|
|
|
onePtrOptimization bool
|
|
|
- fields []structFieldTo
|
|
|
+ fields []structFieldTo
|
|
|
}
|
|
|
|
|
|
type structFieldTo struct {
|