|
|
|
@ -34,15 +34,15 @@ import (
|
|
|
|
type (
|
|
|
|
type (
|
|
|
|
|
|
|
|
|
|
|
|
RTypeFields struct {
|
|
|
|
RTypeFields struct {
|
|
|
|
RFields []RField
|
|
|
|
Fields RFields
|
|
|
|
Index map[string]int
|
|
|
|
Index map[string]int
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func NewRTypeRFields (t reflect.Type) *RTypeFields {
|
|
|
|
func NewRTypeFields (t reflect.Type) *RTypeFields {
|
|
|
|
// Anonymous RFields to explore at the current level and the next.
|
|
|
|
// Anonymous Fields to explore at the current level and the next.
|
|
|
|
current := []RField{}
|
|
|
|
current := RFields{}
|
|
|
|
next := []RField{{RType: t}}
|
|
|
|
next := []RField{{RType: t}}
|
|
|
|
|
|
|
|
|
|
|
|
// Count of queued names for current level and the next.
|
|
|
|
// Count of queued names for current level and the next.
|
|
|
|
@ -51,8 +51,8 @@ func NewRTypeRFields (t reflect.Type) *RTypeFields {
|
|
|
|
// Types already visited at an earlier level.
|
|
|
|
// Types already visited at an earlier level.
|
|
|
|
visited := map[reflect.Type]bool{}
|
|
|
|
visited := map[reflect.Type]bool{}
|
|
|
|
|
|
|
|
|
|
|
|
// RFields found.
|
|
|
|
// Fields found.
|
|
|
|
var RFields []RField
|
|
|
|
var fs []RField
|
|
|
|
|
|
|
|
|
|
|
|
// Buffer to run HTMLEscape on RField names.
|
|
|
|
// Buffer to run HTMLEscape on RField names.
|
|
|
|
var nameEscBuf bytes.Buffer
|
|
|
|
var nameEscBuf bytes.Buffer
|
|
|
|
@ -67,7 +67,7 @@ func NewRTypeRFields (t reflect.Type) *RTypeFields {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
visited[f.RType] = true
|
|
|
|
visited[f.RType] = true
|
|
|
|
|
|
|
|
|
|
|
|
// Scan f.RType for RFields to include.
|
|
|
|
// Scan f.RType for Fields to include.
|
|
|
|
for i := 0; i < f.RType.NumField(); i++ {
|
|
|
|
for i := 0; i < f.RType.NumField(); i++ {
|
|
|
|
var flags RFieldFlags
|
|
|
|
var flags RFieldFlags
|
|
|
|
sf := f.RType.Field(i)
|
|
|
|
sf := f.RType.Field(i)
|
|
|
|
@ -77,13 +77,13 @@ func NewRTypeRFields (t reflect.Type) *RTypeFields {
|
|
|
|
t = t.Elem()
|
|
|
|
t = t.Elem()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !sf.IsExported() && t.Kind() != reflect.Struct {
|
|
|
|
if !sf.IsExported() && t.Kind() != reflect.Struct {
|
|
|
|
// Ignore embedded RFields of unexported non-struct types.
|
|
|
|
// Ignore embedded Fields of unexported non-struct types.
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Do not ignore embedded RFields of unexported struct types
|
|
|
|
// Do not ignore embedded Fields of unexported struct types
|
|
|
|
// since they may have exported RFields.
|
|
|
|
// since they may have exported Fields.
|
|
|
|
} else if !sf.IsExported() {
|
|
|
|
} else if !sf.IsExported() {
|
|
|
|
// Ignore unexported non-embedded RFields.
|
|
|
|
// Ignore unexported non-embedded Fields.
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tag := sf.Tag.Get("json")
|
|
|
|
tag := sf.Tag.Get("json")
|
|
|
|
@ -118,7 +118,9 @@ func NewRTypeRFields (t reflect.Type) *RTypeFields {
|
|
|
|
|
|
|
|
|
|
|
|
// Record found RField and index sequence.
|
|
|
|
// Record found RField and index sequence.
|
|
|
|
if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
|
|
|
|
if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
|
|
|
|
tagged := name != ""
|
|
|
|
if name != "" {
|
|
|
|
|
|
|
|
flags |= RFieldFlagTagged
|
|
|
|
|
|
|
|
}
|
|
|
|
if name == "" {
|
|
|
|
if name == "" {
|
|
|
|
name = sf.Name
|
|
|
|
name = sf.Name
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -145,13 +147,13 @@ func NewRTypeRFields (t reflect.Type) *RTypeFields {
|
|
|
|
rf.HName = nameEscBuf.String()
|
|
|
|
rf.HName = nameEscBuf.String()
|
|
|
|
//rf. = `"` + rf.Name + `":`
|
|
|
|
//rf. = `"` + rf.Name + `":`
|
|
|
|
|
|
|
|
|
|
|
|
RFields = append(RFields, rf)
|
|
|
|
fs = append(fs, rf)
|
|
|
|
if count[f.RType] > 1 {
|
|
|
|
if count[f.RType] > 1 {
|
|
|
|
// If there were multiple instances, add a second,
|
|
|
|
// If there were multiple instances, add a second,
|
|
|
|
// so that the annihilation code will see a duplicate.
|
|
|
|
// so that the annihilation code will see a duplicate.
|
|
|
|
// It only cares about the distinction between 1 or 2,
|
|
|
|
// It only cares about the distinction between 1 or 2,
|
|
|
|
// so don't bother generating any more copies.
|
|
|
|
// so don't bother generating any more copies.
|
|
|
|
RFields = append(RFields, RFields[len(RFields)-1])
|
|
|
|
fs = append(fs, fs[len(fs)-1])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -165,8 +167,8 @@ func NewRTypeRFields (t reflect.Type) *RTypeFields {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sort.Slice(RFields, func(i, j int) bool {
|
|
|
|
sort.Slice(fs, func(i, j int) bool {
|
|
|
|
x := RFields
|
|
|
|
x := fs
|
|
|
|
// sort RField by name, breaking ties with depth, then
|
|
|
|
// sort RField by name, breaking ties with depth, then
|
|
|
|
// breaking ties with "name came from json tag", then
|
|
|
|
// breaking ties with "name came from json tag", then
|
|
|
|
// breaking ties with index sequence.
|
|
|
|
// breaking ties with index sequence.
|
|
|
|
@ -176,26 +178,26 @@ func NewRTypeRFields (t reflect.Type) *RTypeFields {
|
|
|
|
if len(x[i].Index) != len(x[j].Index) {
|
|
|
|
if len(x[i].Index) != len(x[j].Index) {
|
|
|
|
return len(x[i].Index) < len(x[j].Index)
|
|
|
|
return len(x[i].Index) < len(x[j].Index)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if x[i].Flags.Tagged() != x[j].Flags.Tagged() {
|
|
|
|
if x[i].Tagged() != x[j].Tagged() {
|
|
|
|
return x[i].Flags.Tagged()
|
|
|
|
return x[i].Tagged()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return RFieldsByIndex(x).Less(i, j)
|
|
|
|
return RFieldsByIndex(x).Less(i, j)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// Delete all RFields that are hidden by the Go rules for embedded RFields,
|
|
|
|
// Delete all Fields that are hidden by the Go rules for embedded Fields,
|
|
|
|
// except that RFields with JSON tags are promoted.
|
|
|
|
// except that Fields with JSON tags are promoted.
|
|
|
|
|
|
|
|
|
|
|
|
// The RFields are sorted in primary order of name, secondary order
|
|
|
|
// The Fields are sorted in primary order of name, secondary order
|
|
|
|
// of RField index length. Loop over names; for each name, delete
|
|
|
|
// of RField index length. Loop over names; for each name, delete
|
|
|
|
// hidden RFields by choosing the one dominant RField that survives.
|
|
|
|
// hidden Fields by choosing the one dominant RField that survives.
|
|
|
|
out := RFields[:0]
|
|
|
|
out := fs[:0]
|
|
|
|
for advance, i := 0, 0; i < len(RFields); i += advance {
|
|
|
|
for advance, i := 0, 0; i < len(fs); i += advance {
|
|
|
|
// One iteration per name.
|
|
|
|
// One iteration per name.
|
|
|
|
// Find the sequence of RFields with the name of this first RField.
|
|
|
|
// Find the sequence of Fields with the name of this first RField.
|
|
|
|
fi := RFields[i]
|
|
|
|
fi := fs[i]
|
|
|
|
name := fi.Name
|
|
|
|
name := fi.Name
|
|
|
|
for advance = 1; i+advance < len(RFields); advance++ {
|
|
|
|
for advance = 1; i+advance < len(fs); advance++ {
|
|
|
|
fj := RFields[i+advance]
|
|
|
|
fj := fs[i+advance]
|
|
|
|
if fj.Name != name {
|
|
|
|
if fj.Name != name {
|
|
|
|
break
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -204,45 +206,31 @@ func NewRTypeRFields (t reflect.Type) *RTypeFields {
|
|
|
|
out = append(out, fi)
|
|
|
|
out = append(out, fi)
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dominant, ok := dominantRField(RFields[i : i+advance])
|
|
|
|
dominant, ok := RFields(fs[i : i+advance]).Dominant()
|
|
|
|
if ok {
|
|
|
|
if ok {
|
|
|
|
out = append(out, dominant)
|
|
|
|
out = append(out, dominant)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RFields = out
|
|
|
|
fs = out
|
|
|
|
sort.Sort(RFieldsByIndex(RFields))
|
|
|
|
sort.Sort(RFieldsByIndex(fs))
|
|
|
|
|
|
|
|
|
|
|
|
for i := range RFields {
|
|
|
|
for i := range fs {
|
|
|
|
//f := &RFields[i]
|
|
|
|
//f := &fs[i]
|
|
|
|
//f.encoder = typeEncoder(typeByIndex(t, f.index))
|
|
|
|
//f.encoder = typeEncoder(typeByIndex(t, f.index))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nameIndex := make(map[string]int, len(RFields))
|
|
|
|
nameIndex := make(map[string]int, len(fs))
|
|
|
|
for i, RField := range RFields {
|
|
|
|
for i, f := range fs {
|
|
|
|
nameIndex[RField.Name] = i
|
|
|
|
nameIndex[f.Name] = i
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return &RTypeFields{
|
|
|
|
return &RTypeFields{
|
|
|
|
RFields: RFields,
|
|
|
|
Fields: fs,
|
|
|
|
Index : nameIndex,
|
|
|
|
Index : nameIndex,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// dominantRField looks through the RFields, all of which are known to
|
|
|
|
|
|
|
|
// have the same name, to find the single RField that dominates the
|
|
|
|
|
|
|
|
// others using Go's embedding rules, modified by the presence of
|
|
|
|
|
|
|
|
// JSON tags. If there are multiple top-level RFields, the boolean
|
|
|
|
|
|
|
|
// will be false: This condition is an error in Go and we skip all
|
|
|
|
|
|
|
|
// the RFields.
|
|
|
|
|
|
|
|
func dominantRField(RFields []RField) (RField, bool) {
|
|
|
|
|
|
|
|
// The RFields are sorted in increasing index-length order, then by presence of tag.
|
|
|
|
|
|
|
|
// That means that the first RField is the dominant one. We need only check
|
|
|
|
|
|
|
|
// for error cases: two RFields at top level, either both tagged or neither tagged.
|
|
|
|
|
|
|
|
if len(RFields) > 1 && len(RFields[0].Index) == len(RFields[1].Index) && RFields[0].Tag == Fields[1].Tag {
|
|
|
|
|
|
|
|
return RField{}, false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return RFields[0], true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func parseTag(tag string) (string, tagOptions) {
|
|
|
|
func parseTag(tag string) (string, tagOptions) {
|
|
|
|
|