From c1b2bdc1083af4e1567198f4d421a057a6239b11 Mon Sep 17 00:00:00 2001 From: Victor Starodub Date: Tue, 5 Apr 2016 02:00:33 +0300 Subject: [PATCH] Support embedded pointer fields. --- gen/decoder.go | 36 ++++++++++++++++++++++++++++++++---- gen/encoder.go | 6 +++++- tests/data.go | 11 ++++++++++- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/gen/decoder.go b/gen/decoder.go index fbc9f79..c01ea38 100644 --- a/gen/decoder.go +++ b/gen/decoder.go @@ -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 } diff --git a/gen/encoder.go b/gen/encoder.go index bd590ca..43e6dba 100644 --- a/gen/encoder.go +++ b/gen/encoder.go @@ -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 } diff --git a/tests/data.go b/tests/data.go index 6cd40df..307e42f 100644 --- a/tests/data.go +++ b/tests/data.go @@ -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"` + "}"