redefiniendo el builder

packs2
DEV 3 years ago
parent bfb4c0777e
commit f8b03447aa

@ -28,8 +28,8 @@ import "reflect"
type (
RField struct {
RFieldFlags
RType reflect.Type
Flags RFieldFlags
Name string
SName string // scaped name
@ -40,9 +40,22 @@ type (
BName []byte // name bytes
Index []int
}
RFields []RField
)
func (f RFields) Dominant() (RField, bool) {
// The Fields 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 Fields at top level, either both tagged or neither tagged.
if len(f) > 1 && len(f[0].Index) == len(f[1].Index) && f[0].Tagged() == f[1].Tagged() {
return RField{}, false
}
return f[0], true
}

@ -34,15 +34,15 @@ import (
type (
RTypeFields struct {
RFields []RField
Index map[string]int
Fields RFields
Index map[string]int
}
)
func NewRTypeRFields (t reflect.Type) *RTypeFields {
// Anonymous RFields to explore at the current level and the next.
current := []RField{}
func NewRTypeFields (t reflect.Type) *RTypeFields {
// Anonymous Fields to explore at the current level and the next.
current := RFields{}
next := []RField{{RType: t}}
// 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.
visited := map[reflect.Type]bool{}
// RFields found.
var RFields []RField
// Fields found.
var fs []RField
// Buffer to run HTMLEscape on RField names.
var nameEscBuf bytes.Buffer
@ -67,7 +67,7 @@ func NewRTypeRFields (t reflect.Type) *RTypeFields {
}
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++ {
var flags RFieldFlags
sf := f.RType.Field(i)
@ -77,13 +77,13 @@ func NewRTypeRFields (t reflect.Type) *RTypeFields {
t = t.Elem()
}
if !sf.IsExported() && t.Kind() != reflect.Struct {
// Ignore embedded RFields of unexported non-struct types.
// Ignore embedded Fields of unexported non-struct types.
continue
}
// Do not ignore embedded RFields of unexported struct types
// since they may have exported RFields.
// Do not ignore embedded Fields of unexported struct types
// since they may have exported Fields.
} else if !sf.IsExported() {
// Ignore unexported non-embedded RFields.
// Ignore unexported non-embedded Fields.
continue
}
tag := sf.Tag.Get("json")
@ -118,7 +118,9 @@ func NewRTypeRFields (t reflect.Type) *RTypeFields {
// Record found RField and index sequence.
if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
tagged := name != ""
if name != "" {
flags |= RFieldFlagTagged
}
if name == "" {
name = sf.Name
}
@ -145,13 +147,13 @@ func NewRTypeRFields (t reflect.Type) *RTypeFields {
rf.HName = nameEscBuf.String()
//rf. = `"` + rf.Name + `":`
RFields = append(RFields, rf)
fs = append(fs, rf)
if count[f.RType] > 1 {
// If there were multiple instances, add a second,
// so that the annihilation code will see a duplicate.
// It only cares about the distinction between 1 or 2,
// so don't bother generating any more copies.
RFields = append(RFields, RFields[len(RFields)-1])
fs = append(fs, fs[len(fs)-1])
}
continue
}
@ -165,8 +167,8 @@ func NewRTypeRFields (t reflect.Type) *RTypeFields {
}
}
sort.Slice(RFields, func(i, j int) bool {
x := RFields
sort.Slice(fs, func(i, j int) bool {
x := fs
// sort RField by name, breaking ties with depth, then
// breaking ties with "name came from json tag", then
// breaking ties with index sequence.
@ -176,26 +178,26 @@ func NewRTypeRFields (t reflect.Type) *RTypeFields {
if 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() {
return x[i].Flags.Tagged()
if x[i].Tagged() != x[j].Tagged() {
return x[i].Tagged()
}
return RFieldsByIndex(x).Less(i, j)
})
// Delete all RFields that are hidden by the Go rules for embedded RFields,
// except that RFields with JSON tags are promoted.
// Delete all Fields that are hidden by the Go rules for embedded Fields,
// 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
// hidden RFields by choosing the one dominant RField that survives.
out := RFields[:0]
for advance, i := 0, 0; i < len(RFields); i += advance {
// hidden Fields by choosing the one dominant RField that survives.
out := fs[:0]
for advance, i := 0, 0; i < len(fs); i += advance {
// One iteration per name.
// Find the sequence of RFields with the name of this first RField.
fi := RFields[i]
// Find the sequence of Fields with the name of this first RField.
fi := fs[i]
name := fi.Name
for advance = 1; i+advance < len(RFields); advance++ {
fj := RFields[i+advance]
for advance = 1; i+advance < len(fs); advance++ {
fj := fs[i+advance]
if fj.Name != name {
break
}
@ -204,45 +206,31 @@ func NewRTypeRFields (t reflect.Type) *RTypeFields {
out = append(out, fi)
continue
}
dominant, ok := dominantRField(RFields[i : i+advance])
dominant, ok := RFields(fs[i : i+advance]).Dominant()
if ok {
out = append(out, dominant)
}
}
RFields = out
sort.Sort(RFieldsByIndex(RFields))
fs = out
sort.Sort(RFieldsByIndex(fs))
for i := range RFields {
//f := &RFields[i]
for i := range fs {
//f := &fs[i]
//f.encoder = typeEncoder(typeByIndex(t, f.index))
}
nameIndex := make(map[string]int, len(RFields))
for i, RField := range RFields {
nameIndex[RField.Name] = i
nameIndex := make(map[string]int, len(fs))
for i, f := range fs {
nameIndex[f.Name] = i
}
return &RTypeFields{
RFields: RFields,
Index : nameIndex,
Fields: fs,
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) {

Loading…
Cancel
Save

Powered by TurnKey Linux.