Support embedded pointer fields.

This commit is contained in:
Victor Starodub
2016-04-05 02:00:33 +03:00
parent bc7232a0c0
commit c1b2bdc108
3 changed files with 47 additions and 6 deletions
+32 -4
View File
@@ -162,7 +162,11 @@ func mergeStructFields(fields1, fields2 []reflect.StructField) (fields []reflect
return
}
func getStructFields(t reflect.Type) []reflect.StructField {
func getStructFields(t reflect.Type) ([]reflect.StructField, error) {
if t.Kind() != reflect.Struct {
return nil, fmt.Errorf("got %v; expected a struct", t)
}
var efields []reflect.StructField
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
@@ -170,7 +174,16 @@ func getStructFields(t reflect.Type) []reflect.StructField {
continue
}
efields = mergeStructFields(efields, getStructFields(f.Type))
t1 := f.Type
if t1.Kind() == reflect.Ptr {
t1 = t1.Elem()
}
fs, err := getStructFields(t1)
if err != nil {
return nil, fmt.Errorf("error processing embedded field: %v", err)
}
efields = mergeStructFields(efields, fs)
}
var fields []reflect.StructField
@@ -185,7 +198,7 @@ func getStructFields(t reflect.Type) []reflect.StructField {
fields = append(fields, f)
}
}
return mergeStructFields(efields, fields)
return mergeStructFields(efields, fields), nil
}
func (g *Generator) genStructDecoder(t reflect.Type) error {
@@ -197,6 +210,16 @@ func (g *Generator) genStructDecoder(t reflect.Type) error {
typ := g.getType(t)
fmt.Fprintln(g.out, "func "+fname+"(in *jlexer.Lexer, out *"+typ+") {")
// Init embedded pointer fields.
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if !f.Anonymous || f.Type.Kind() != reflect.Ptr {
continue
}
fmt.Fprintln(g.out, " out."+f.Name+" = new("+g.getType(f.Type.Elem())+")")
}
fmt.Fprintln(g.out, " in.Delim('{')")
fmt.Fprintln(g.out, " for !in.IsDelim('}') {")
fmt.Fprintln(g.out, " key := in.UnsafeString()")
@@ -208,7 +231,12 @@ func (g *Generator) genStructDecoder(t reflect.Type) error {
fmt.Fprintln(g.out, " }")
fmt.Fprintln(g.out, " switch key {")
for _, f := range getStructFields(t) {
fs, err := getStructFields(t)
if err != nil {
return fmt.Errorf("cannot generate decoder for %v: %v", t, err)
}
for _, f := range fs {
if err := g.genStructFieldDecoder(t, f); err != nil {
return err
}
+5 -1
View File
@@ -185,7 +185,11 @@ func (g *Generator) genStructEncoder(t reflect.Type) error {
fmt.Fprintln(g.out, " first := true")
fmt.Fprintln(g.out, " _ = first")
for _, f := range getStructFields(t) {
fs, err := getStructFields(t)
if err != nil {
return fmt.Errorf("cannot generate encoder for %v: %v", t, err)
}
for _, f := range fs {
if err := g.genStructFieldEncoder(t, f); err != nil {
return err
}
+10 -1
View File
@@ -174,10 +174,16 @@ type SubStruct struct {
unexpored bool
}
type SubP struct {
V string
}
type SubStructAlias SubStruct
type Structs struct {
SubStruct
*SubP
Value2 int
Sub1 SubStruct `json:"substruct"`
@@ -209,7 +215,9 @@ type Structs struct {
var structsValue = Structs{
SubStruct: SubStruct{Value: "test"},
Value2: 5,
SubP: &SubP{V: "subp"},
Value2: 5,
Sub1: SubStruct{Value: "test1", Value2: "v"},
Sub2: &SubStruct{Value: "test2", Value2: "v2"},
@@ -263,6 +271,7 @@ var structsString = "{" +
`"AnonymousPtrSlice":[{"V":3},{"V":4}],` +
// Embedded fields go last.
`"V":"subp",` +
`"Value":"test"` +
"}"