redefiniendo el builder

packs2
DEV 3 years ago
parent bfb4c0777e
commit f8b03447aa

@ -28,8 +28,8 @@ import "reflect"
type ( type (
RField struct { RField struct {
RFieldFlags
RType reflect.Type RType reflect.Type
Flags RFieldFlags
Name string Name string
SName string // scaped name SName string // scaped name
@ -40,9 +40,22 @@ type (
BName []byte // name bytes BName []byte // name bytes
Index []int 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 ( 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) {

Loading…
Cancel
Save

Powered by TurnKey Linux.