gojay

high performance JSON encoder/decoder with stream API for Golang
git clone git://git.lair.cx/gojay
Log | Files | Refs | README | LICENSE

commit ea31b296341595ece17e747a1dd24f260af48cf7
parent f801fd9a9b630c005451ac293c7ca64fa1123be4
Author: francoispqt <francois@parquet.ninja>
Date:   Sun, 24 Jun 2018 00:42:14 +0800

refactor error handling in generator

Diffstat:
Mencode_array_test.go | 5+++++
Mgojay/Makefile | 8++++++--
Mgojay/gen.go | 32++++++++++++++++++++++++++++++--
Mgojay/gen_array_test.go | 6+++++-
Mgojay/gen_map_marshal.go | 115++++++++++++++++++++++---------------------------------------------------------
Mgojay/gen_map_test.go | 348++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mgojay/gen_map_unmarshal.go | 114++++++++++++++++++++++++++-----------------------------------------------------
Mgojay/gen_parse.go | 4++--
Mgojay/gen_struct_marshal.go | 102++++++++++++++++++++++++-------------------------------------------------------
Mgojay/gen_struct_test.go | 20++++++++++++++++++--
Mgojay/gen_struct_unmarshal.go | 148++++++++++++++++++++++++++++++++-----------------------------------------------
Mgojay/gen_struct_unmarshal_tpl.go | 8++++++++
Mgojay/gen_test.go | 4++--
Mgojay/main.go | 33++++++++++++++++++++++++++++-----
Dgojay/tests/complex_structs.go | 1-
Agojay/tests/json.go | 284+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Agojay/tests/maps.go | 4++++
Rgojay/tests/basic_slices.go -> gojay/tests/slices.go | 0
Rgojay/tests/basic_structs.go -> gojay/tests/structs.go | 0
Mgojay/visitor.go | 6+++---
20 files changed, 901 insertions(+), 341 deletions(-)

diff --git a/encode_array_test.go b/encode_array_test.go @@ -331,3 +331,8 @@ func TestEncoderArrErrors(t *testing.T) { assert.True(t, false, "should not be called as it should have panicked") }) } + +func TestEncoderArrayFunc(t *testing.T) { + var f EncodeArrayFunc + assert.True(t, f.IsNil()) +} diff --git a/gojay/Makefile b/gojay/Makefile @@ -8,4 +8,8 @@ test: .PHONY: cover cover: - go test -tags test -coverprofile=profile.out -\ No newline at end of file + go test -tags test -coverprofile=coverage.out + +.PHONY: coverhtml +coverhtml: + go tool cover -html=coverage.out +\ No newline at end of file diff --git a/gojay/gen.go b/gojay/gen.go @@ -11,12 +11,15 @@ const gojayAnnotation = "//gojay:json" const genFileSuffix = "_gojay.go" var pkgTpl *template.Template +var genHeader = []byte("// Code generated by GoJay. DO NOT EDIT.\n\n") var gojayImport = []byte("import \"github.com/francoispqt/gojay\"\n") +// Gen is the structure representing a generator type Gen struct { b *strings.Builder pkg string src string + types []string genTypes map[string]*ast.TypeSpec vis *vis } @@ -48,9 +51,10 @@ func parseTemplates(tpls templateList, pfx string) { } // NewGen returns a new generator -func NewGen(p string) *Gen { +func NewGen(p string, types []string) *Gen { g := &Gen{ src: p, + types: types, b: &strings.Builder{}, genTypes: make(map[string]*ast.TypeSpec), } @@ -77,9 +81,33 @@ func (g *Gen) writeGojayImport() error { return nil } +func (g *Gen) writeGenHeader() error { + _, err := g.b.Write(genHeader) + if err != nil { + return err + } + return nil +} + +func (g *Gen) isGenType(typeName string) bool { + // check if type is in types + for _, t := range g.types { + if t == typeName { + return true + } + } + return false +} + +// Gen starts the generation writing to the string builder func (g *Gen) Gen() error { + err := g.writeGenHeader() + if err != nil { + return err + } + // write package - err := g.writePkg(g.pkg) + err = g.writePkg(g.pkg) if err != nil { return err } diff --git a/gojay/gen_array_test.go b/gojay/gen_array_test.go @@ -360,7 +360,11 @@ func (v *SliceStrSlice) IsNil() bool { if err != nil { t.Fatal(err) } - assert.Equal(t, testCase.expectedResult, g.b.String()) + assert.Equal( + t, + string(genHeader)+testCase.expectedResult, + g.b.String(), + ) }) } } diff --git a/gojay/gen_map_marshal.go b/gojay/gen_map_marshal.go @@ -3,6 +3,7 @@ package main import ( "errors" "go/ast" + "log" ) func (g *Gen) mapGenIsNil(n string) error { @@ -52,81 +53,37 @@ func (g *Gen) mapGenMarshalObj(n string, s *ast.MapType) error { func (g *Gen) mapGenMarshalIdent(i *ast.Ident, ptr bool) error { switch i.String() { case "string": - var err = g.mapMarshalString(ptr) - if err != nil { - return err - } + g.mapMarshalString(ptr) case "bool": - var err = g.mapMarshalBool(ptr) - if err != nil { - return err - } + g.mapMarshalBool(ptr) case "int": - var err = g.mapMarshalInt("", ptr) - if err != nil { - return err - } + g.mapMarshalInt("", ptr) case "int64": - var err = g.mapMarshalInt("64", ptr) - if err != nil { - return err - } + g.mapMarshalInt("64", ptr) case "int32": - var err = g.mapMarshalInt("32", ptr) - if err != nil { - return err - } + g.mapMarshalInt("32", ptr) case "int16": - var err = g.mapMarshalInt("16", ptr) - if err != nil { - return err - } + g.mapMarshalInt("16", ptr) case "int8": - var err = g.mapMarshalInt("8", ptr) - if err != nil { - return err - } + g.mapMarshalInt("8", ptr) case "uint64": - var err = g.mapMarshalUint("64", ptr) - if err != nil { - return err - } + g.mapMarshalUint("64", ptr) case "uint32": - var err = g.mapMarshalUint("32", ptr) - if err != nil { - return err - } + g.mapMarshalUint("32", ptr) case "uint16": - var err = g.mapMarshalUint("16", ptr) - if err != nil { - return err - } + g.mapMarshalUint("16", ptr) case "uint8": - var err = g.mapMarshalUint("8", ptr) - if err != nil { - return err - } + g.mapMarshalUint("8", ptr) case "float64": - var err = g.mapMarshalFloat("", ptr) - if err != nil { - return err - } + g.mapMarshalFloat("", ptr) default: // if ident is already in our spec list if sp, ok := g.genTypes[i.Name]; ok { - err := g.mapMarshalNonPrim(sp, ptr) - if err != nil { - return err - } - + g.mapMarshalNonPrim(sp, ptr) } else if i.Obj != nil { switch t := i.Obj.Decl.(type) { case *ast.TypeSpec: - var err = g.mapMarshalNonPrim(t, ptr) - if err != nil { - return err - } - + g.mapMarshalNonPrim(t, ptr) default: return errors.New("could not determine what to do with type " + i.String()) } @@ -137,17 +94,16 @@ func (g *Gen) mapGenMarshalIdent(i *ast.Ident, ptr bool) error { return nil } -func (g *Gen) mapMarshalNonPrim(sp *ast.TypeSpec, ptr bool) error { +func (g *Gen) mapMarshalNonPrim(sp *ast.TypeSpec, ptr bool) { switch sp.Type.(type) { case *ast.StructType: - return g.mapMarshalStruct(sp, ptr) + g.mapMarshalStruct(sp, ptr) case *ast.ArrayType: - return g.mapMarshalArr(sp, ptr) + g.mapMarshalArr(sp, ptr) } - return nil } -func (g *Gen) mapMarshalString(ptr bool) error { +func (g *Gen) mapMarshalString(ptr bool) { ptrStr := "" if ptr { ptrStr = "*" @@ -156,12 +112,11 @@ func (g *Gen) mapMarshalString(ptr bool) error { Ptr string }{ptrStr}) if err != nil { - return err + log.Fatal(err) } - return nil } -func (g *Gen) mapMarshalBool(ptr bool) error { +func (g *Gen) mapMarshalBool(ptr bool) { ptrStr := "" if ptr { ptrStr = "*" @@ -170,12 +125,11 @@ func (g *Gen) mapMarshalBool(ptr bool) error { Ptr string }{ptrStr}) if err != nil { - return err + log.Fatal(err) } - return nil } -func (g *Gen) mapMarshalInt(intLen string, ptr bool) error { +func (g *Gen) mapMarshalInt(intLen string, ptr bool) { ptrStr := "" if ptr { ptrStr = "*" @@ -185,12 +139,11 @@ func (g *Gen) mapMarshalInt(intLen string, ptr bool) error { Ptr string }{intLen, ptrStr}) if err != nil { - return err + log.Fatal(err) } - return nil } -func (g *Gen) mapMarshalUint(intLen string, ptr bool) error { +func (g *Gen) mapMarshalUint(intLen string, ptr bool) { ptrStr := "" if ptr { ptrStr = "*" @@ -200,12 +153,11 @@ func (g *Gen) mapMarshalUint(intLen string, ptr bool) error { Ptr string }{intLen, ptrStr}) if err != nil { - return err + log.Fatal(err) } - return nil } -func (g *Gen) mapMarshalFloat(intLen string, ptr bool) error { +func (g *Gen) mapMarshalFloat(intLen string, ptr bool) { ptrStr := "" if ptr { ptrStr = "*" @@ -215,12 +167,11 @@ func (g *Gen) mapMarshalFloat(intLen string, ptr bool) error { Ptr string }{intLen, ptrStr}) if err != nil { - return err + log.Fatal(err) } - return nil } -func (g *Gen) mapMarshalStruct(st *ast.TypeSpec, ptr bool) error { +func (g *Gen) mapMarshalStruct(st *ast.TypeSpec, ptr bool) { ptrStr := "" if ptr { ptrStr = "*" @@ -229,12 +180,11 @@ func (g *Gen) mapMarshalStruct(st *ast.TypeSpec, ptr bool) error { Ptr string }{ptrStr}) if err != nil { - return err + log.Fatal(err) } - return nil } -func (g *Gen) mapMarshalArr(st *ast.TypeSpec, ptr bool) error { +func (g *Gen) mapMarshalArr(st *ast.TypeSpec, ptr bool) { ptrStr := "" if ptr { ptrStr = "*" @@ -243,7 +193,6 @@ func (g *Gen) mapMarshalArr(st *ast.TypeSpec, ptr bool) error { Ptr string }{ptrStr}) if err != nil { - return err + log.Fatal(err) } - return nil } diff --git a/gojay/gen_map_test.go b/gojay/gen_map_test.go @@ -82,6 +82,348 @@ func (v IntMap) MarshalJSONObject(enc *gojay.Encoder) { func (v IntMap) IsNil() bool { return v == nil || len(v) == 0 } `, }, + "basicMapStringInt64": { + input: strings.NewReader(`package test + +//gojay:json +type IntMap map[string]int64 +`), + expectedResult: `package + +import "github.com/francoispqt/gojay" + +// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject +func (v IntMap) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { + var i int64 + if err := dec.Int64(&i); err != nil { + return err + } + v[k] = i + return nil +} + +// NKeys returns the number of keys to unmarshal +func (v IntMap) NKeys() int { return 0 } + +// MarshalJSONObject implements gojay's MarshalerJSONObject +func (v IntMap) MarshalJSONObject(enc *gojay.Encoder) { + for k, s := range v { + enc.Int64Key(k, s) + } +} + +// IsNil returns wether the structure is nil value or not +func (v IntMap) IsNil() bool { return v == nil || len(v) == 0 } +`, + }, + "basicMapStringInt32": { + input: strings.NewReader(`package test + +//gojay:json +type IntMap map[string]int32 +`), + expectedResult: `package + +import "github.com/francoispqt/gojay" + +// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject +func (v IntMap) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { + var i int32 + if err := dec.Int32(&i); err != nil { + return err + } + v[k] = i + return nil +} + +// NKeys returns the number of keys to unmarshal +func (v IntMap) NKeys() int { return 0 } + +// MarshalJSONObject implements gojay's MarshalerJSONObject +func (v IntMap) MarshalJSONObject(enc *gojay.Encoder) { + for k, s := range v { + enc.Int32Key(k, s) + } +} + +// IsNil returns wether the structure is nil value or not +func (v IntMap) IsNil() bool { return v == nil || len(v) == 0 } +`, + }, + "basicMapStringInt16": { + input: strings.NewReader(`package test + +//gojay:json +type IntMap map[string]int16 +`), + expectedResult: `package + +import "github.com/francoispqt/gojay" + +// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject +func (v IntMap) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { + var i int16 + if err := dec.Int16(&i); err != nil { + return err + } + v[k] = i + return nil +} + +// NKeys returns the number of keys to unmarshal +func (v IntMap) NKeys() int { return 0 } + +// MarshalJSONObject implements gojay's MarshalerJSONObject +func (v IntMap) MarshalJSONObject(enc *gojay.Encoder) { + for k, s := range v { + enc.Int16Key(k, s) + } +} + +// IsNil returns wether the structure is nil value or not +func (v IntMap) IsNil() bool { return v == nil || len(v) == 0 } +`, + }, + "basicMapStringInt8": { + input: strings.NewReader(`package test + +//gojay:json +type IntMap map[string]int8 +`), + expectedResult: `package + +import "github.com/francoispqt/gojay" + +// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject +func (v IntMap) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { + var i int8 + if err := dec.Int8(&i); err != nil { + return err + } + v[k] = i + return nil +} + +// NKeys returns the number of keys to unmarshal +func (v IntMap) NKeys() int { return 0 } + +// MarshalJSONObject implements gojay's MarshalerJSONObject +func (v IntMap) MarshalJSONObject(enc *gojay.Encoder) { + for k, s := range v { + enc.Int8Key(k, s) + } +} + +// IsNil returns wether the structure is nil value or not +func (v IntMap) IsNil() bool { return v == nil || len(v) == 0 } +`, + }, + "basicMapStringUint64": { + input: strings.NewReader(`package test + +//gojay:json +type IntMap map[string]uint64 +`), + expectedResult: `package + +import "github.com/francoispqt/gojay" + +// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject +func (v IntMap) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { + var i uint64 + if err := dec.Uint64(&i); err != nil { + return err + } + v[k] = i + return nil +} + +// NKeys returns the number of keys to unmarshal +func (v IntMap) NKeys() int { return 0 } + +// MarshalJSONObject implements gojay's MarshalerJSONObject +func (v IntMap) MarshalJSONObject(enc *gojay.Encoder) { + for k, s := range v { + enc.Uint64Key(k, s) + } +} + +// IsNil returns wether the structure is nil value or not +func (v IntMap) IsNil() bool { return v == nil || len(v) == 0 } +`, + }, + "basicMapStringUint32": { + input: strings.NewReader(`package test + +//gojay:json +type IntMap map[string]uint32 +`), + expectedResult: `package + +import "github.com/francoispqt/gojay" + +// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject +func (v IntMap) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { + var i uint32 + if err := dec.Uint32(&i); err != nil { + return err + } + v[k] = i + return nil +} + +// NKeys returns the number of keys to unmarshal +func (v IntMap) NKeys() int { return 0 } + +// MarshalJSONObject implements gojay's MarshalerJSONObject +func (v IntMap) MarshalJSONObject(enc *gojay.Encoder) { + for k, s := range v { + enc.Uint32Key(k, s) + } +} + +// IsNil returns wether the structure is nil value or not +func (v IntMap) IsNil() bool { return v == nil || len(v) == 0 } +`, + }, + "basicMapStringUint16": { + input: strings.NewReader(`package test + +//gojay:json +type IntMap map[string]uint16 +`), + expectedResult: `package + +import "github.com/francoispqt/gojay" + +// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject +func (v IntMap) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { + var i uint16 + if err := dec.Uint16(&i); err != nil { + return err + } + v[k] = i + return nil +} + +// NKeys returns the number of keys to unmarshal +func (v IntMap) NKeys() int { return 0 } + +// MarshalJSONObject implements gojay's MarshalerJSONObject +func (v IntMap) MarshalJSONObject(enc *gojay.Encoder) { + for k, s := range v { + enc.Uint16Key(k, s) + } +} + +// IsNil returns wether the structure is nil value or not +func (v IntMap) IsNil() bool { return v == nil || len(v) == 0 } +`, + }, + "basicMapStringUint8": { + input: strings.NewReader(`package test + +//gojay:json +type IntMap map[string]uint8 +`), + expectedResult: `package + +import "github.com/francoispqt/gojay" + +// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject +func (v IntMap) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { + var i uint8 + if err := dec.Uint8(&i); err != nil { + return err + } + v[k] = i + return nil +} + +// NKeys returns the number of keys to unmarshal +func (v IntMap) NKeys() int { return 0 } + +// MarshalJSONObject implements gojay's MarshalerJSONObject +func (v IntMap) MarshalJSONObject(enc *gojay.Encoder) { + for k, s := range v { + enc.Uint8Key(k, s) + } +} + +// IsNil returns wether the structure is nil value or not +func (v IntMap) IsNil() bool { return v == nil || len(v) == 0 } +`, + }, + "basicMapStringBool": { + input: strings.NewReader(`package test + +//gojay:json +type BoolMap map[string]bool +`), + expectedResult: `package + +import "github.com/francoispqt/gojay" + +// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject +func (v BoolMap) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { + var b bool + if err := dec.Bool(&b); err != nil { + return err + } + v[k] = b + return nil +} + +// NKeys returns the number of keys to unmarshal +func (v BoolMap) NKeys() int { return 0 } + +// MarshalJSONObject implements gojay's MarshalerJSONObject +func (v BoolMap) MarshalJSONObject(enc *gojay.Encoder) { + for k, s := range v { + enc.BoolKey(k, s) + } +} + +// IsNil returns wether the structure is nil value or not +func (v BoolMap) IsNil() bool { return v == nil || len(v) == 0 } +`, + }, + "basicMapStringStruct": { + input: strings.NewReader(`package test + +//gojay:json +type BoolMap map[string]*Test + +type Test struct{} +`), + expectedResult: `package + +import "github.com/francoispqt/gojay" + +// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject +func (v BoolMap) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { + var s = &Test{} + if err := dec.Object(s); err != nil { + return err + } + v[k] = s + return nil +} + +// NKeys returns the number of keys to unmarshal +func (v BoolMap) NKeys() int { return 0 } + +// MarshalJSONObject implements gojay's MarshalerJSONObject +func (v BoolMap) MarshalJSONObject(enc *gojay.Encoder) { + for k, s := range v { + enc.ObjectKey(k, s) + } +} + +// IsNil returns wether the structure is nil value or not +func (v BoolMap) IsNil() bool { return v == nil || len(v) == 0 } +`, + }, } for n, testCase := range testCases { t.Run(n, func(t *testing.T) { @@ -94,7 +436,11 @@ func (v IntMap) IsNil() bool { return v == nil || len(v) == 0 } t.Fatal(err) } log.Print(g.b.String()) - assert.Equal(t, testCase.expectedResult, g.b.String()) + assert.Equal( + t, + string(genHeader)+testCase.expectedResult, + g.b.String(), + ) }) } } diff --git a/gojay/gen_map_unmarshal.go b/gojay/gen_map_unmarshal.go @@ -3,6 +3,7 @@ package main import ( "errors" "go/ast" + "log" ) func (g *Gen) mapGenNKeys(n string, count int) error { @@ -54,65 +55,29 @@ func (g *Gen) mapGenUnmarshalObj(n string, s *ast.MapType) error { func (g *Gen) mapGenUnmarshalIdent(i *ast.Ident, ptr bool) error { switch i.String() { case "string": - var err = g.mapUnmarshalString(ptr) - if err != nil { - return err - } + g.mapUnmarshalString(ptr) case "bool": - var err = g.mapUnmarshalBool(ptr) - if err != nil { - return err - } + g.mapUnmarshalBool(ptr) case "int": - var err = g.mapUnmarshalInt("", ptr) - if err != nil { - return err - } + g.mapUnmarshalInt("", ptr) case "int64": - var err = g.mapUnmarshalInt("64", ptr) - if err != nil { - return err - } + g.mapUnmarshalInt("64", ptr) case "int32": - var err = g.mapUnmarshalInt("32", ptr) - if err != nil { - return err - } + g.mapUnmarshalInt("32", ptr) case "int16": - var err = g.mapUnmarshalInt("16", ptr) - if err != nil { - return err - } + g.mapUnmarshalInt("16", ptr) case "int8": - var err = g.mapUnmarshalInt("8", ptr) - if err != nil { - return err - } + g.mapUnmarshalInt("8", ptr) case "uint64": - var err = g.mapUnmarshalUint("64", ptr) - if err != nil { - return err - } + g.mapUnmarshalUint("64", ptr) case "uint32": - var err = g.mapUnmarshalUint("32", ptr) - if err != nil { - return err - } + g.mapUnmarshalUint("32", ptr) case "uint16": - var err = g.mapUnmarshalUint("16", ptr) - if err != nil { - return err - } + g.mapUnmarshalUint("16", ptr) case "uint8": - var err = g.mapUnmarshalUint("8", ptr) - if err != nil { - return err - } + g.mapUnmarshalUint("8", ptr) case "float64": - var err = g.mapUnmarshalFloat("", ptr) - if err != nil { - return err - } + g.mapUnmarshalFloat("", ptr) default: // if ident is already in our spec list if sp, ok := g.genTypes[i.Name]; ok { @@ -141,59 +106,59 @@ func (g *Gen) mapGenUnmarshalIdent(i *ast.Ident, ptr bool) error { func (g *Gen) mapUnmarshalNonPrim(sp *ast.TypeSpec, ptr bool) error { switch sp.Type.(type) { case *ast.StructType: - return g.mapUnmarshalStruct(sp, ptr) + g.mapUnmarshalStruct(sp, ptr) + return nil case *ast.ArrayType: - return g.mapUnmarshalArr(sp, ptr) + g.mapUnmarshalArr(sp, ptr) + return nil } return errors.New("Unknown type") } -func (g *Gen) mapUnmarshalString(ptr bool) error { +func (g *Gen) mapUnmarshalString(ptr bool) { if ptr { err := mapUnmarshalTpl["string"].tpl.Execute(g.b, struct { Ptr string }{""}) if err != nil { - return err + log.Fatal(err) } } else { err := mapUnmarshalTpl["string"].tpl.Execute(g.b, struct { Ptr string }{"&"}) if err != nil { - return err + log.Fatal(err) } } - return nil } -func (g *Gen) mapUnmarshalBool(ptr bool) error { +func (g *Gen) mapUnmarshalBool(ptr bool) { if ptr { err := mapUnmarshalTpl["bool"].tpl.Execute(g.b, struct { Ptr string }{""}) if err != nil { - return err + log.Fatal(err) } } else { err := mapUnmarshalTpl["bool"].tpl.Execute(g.b, struct { Ptr string }{"&"}) if err != nil { - return err + log.Fatal(err) } } - return nil } -func (g *Gen) mapUnmarshalInt(intLen string, ptr bool) error { +func (g *Gen) mapUnmarshalInt(intLen string, ptr bool) { if ptr { err := mapUnmarshalTpl["int"].tpl.Execute(g.b, struct { IntLen string Ptr string }{intLen, ""}) if err != nil { - return err + log.Fatal(err) } } else { err := mapUnmarshalTpl["int"].tpl.Execute(g.b, struct { @@ -201,20 +166,19 @@ func (g *Gen) mapUnmarshalInt(intLen string, ptr bool) error { Ptr string }{intLen, "&"}) if err != nil { - return err + log.Fatal(err) } } - return nil } -func (g *Gen) mapUnmarshalUint(intLen string, ptr bool) error { +func (g *Gen) mapUnmarshalUint(intLen string, ptr bool) { if ptr { err := mapUnmarshalTpl["uint"].tpl.Execute(g.b, struct { IntLen string Ptr string }{intLen, ""}) if err != nil { - return err + log.Fatal(err) } } else { err := mapUnmarshalTpl["uint"].tpl.Execute(g.b, struct { @@ -222,20 +186,19 @@ func (g *Gen) mapUnmarshalUint(intLen string, ptr bool) error { Ptr string }{intLen, "&"}) if err != nil { - return err + log.Fatal(err) } } - return nil } -func (g *Gen) mapUnmarshalFloat(intLen string, ptr bool) error { +func (g *Gen) mapUnmarshalFloat(intLen string, ptr bool) { if ptr { err := mapUnmarshalTpl["float"].tpl.Execute(g.b, struct { IntLen string Ptr string }{intLen, ""}) if err != nil { - return err + log.Fatal(err) } } else { err := mapUnmarshalTpl["float"].tpl.Execute(g.b, struct { @@ -243,37 +206,34 @@ func (g *Gen) mapUnmarshalFloat(intLen string, ptr bool) error { Ptr string }{intLen, "&"}) if err != nil { - return err + log.Fatal(err) } } - return nil } -func (g *Gen) mapUnmarshalStruct(st *ast.TypeSpec, ptr bool) error { +func (g *Gen) mapUnmarshalStruct(st *ast.TypeSpec, ptr bool) { if ptr { err := mapUnmarshalTpl["structPtr"].tpl.Execute(g.b, struct { StructName string }{st.Name.String()}) if err != nil { - return err + log.Fatal(err) } } else { err := mapUnmarshalTpl["struct"].tpl.Execute(g.b, struct { StructName string }{st.Name.String()}) if err != nil { - return err + log.Fatal(err) } } - return nil } -func (g *Gen) mapUnmarshalArr(st *ast.TypeSpec, ptr bool) error { +func (g *Gen) mapUnmarshalArr(st *ast.TypeSpec, ptr bool) { err := mapUnmarshalTpl["arr"].tpl.Execute(g.b, struct { TypeName string }{st.Name.String()}) if err != nil { - return err + log.Fatal(err) } - return nil } diff --git a/gojay/gen_parse.go b/gojay/gen_parse.go @@ -31,7 +31,7 @@ func (g *Gen) parseDir() error { } // range across packages for pkgName, pkg := range pkgs { - v := NewVisitor(g, pkgName) + v := newVisitor(g, pkgName) g.pkg = pkgName // range on files in package for _, f := range pkg.Files { @@ -53,7 +53,7 @@ func (g *Gen) parseFile() error { return err } g.pkg = f.Name.Name - v := NewVisitor(g, g.pkg) + v := newVisitor(g, g.pkg) ast.Walk(v, f) if err != nil { return err diff --git a/gojay/gen_struct_marshal.go b/gojay/gen_struct_marshal.go @@ -3,6 +3,7 @@ package main import ( "errors" "go/ast" + "log" ) func (g *Gen) structGenIsNil(n string) error { @@ -64,76 +65,40 @@ func (g *Gen) structGenMarshalIdent(field *ast.Field, i *ast.Ident, keys int, pt switch i.String() { case "string": - var err = g.structMarshalString(field, keyV, ptr) - if err != nil { - return 0, err - } + g.structMarshalString(field, keyV, ptr) keys++ case "bool": - var err = g.structMarshalBool(field, keyV, ptr) - if err != nil { - return 0, err - } + g.structMarshalBool(field, keyV, ptr) keys++ case "int": - var err = g.structMarshalInt(field, keyV, "", ptr) - if err != nil { - return 0, err - } + g.structMarshalInt(field, keyV, "", ptr) keys++ case "int64": - var err = g.structMarshalInt(field, keyV, "64", ptr) - if err != nil { - return 0, err - } + g.structMarshalInt(field, keyV, "64", ptr) keys++ case "int32": - var err = g.structMarshalInt(field, keyV, "32", ptr) - if err != nil { - return 0, err - } + g.structMarshalInt(field, keyV, "32", ptr) keys++ case "int16": - var err = g.structMarshalInt(field, keyV, "16", ptr) - if err != nil { - return 0, err - } + g.structMarshalInt(field, keyV, "16", ptr) keys++ case "int8": - var err = g.structMarshalInt(field, keyV, "8", ptr) - if err != nil { - return 0, err - } + g.structMarshalInt(field, keyV, "8", ptr) keys++ case "uint64": - var err = g.structMarshalUint(field, keyV, "64", ptr) - if err != nil { - return 0, err - } + g.structMarshalUint(field, keyV, "64", ptr) keys++ case "uint32": - var err = g.structMarshalUint(field, keyV, "32", ptr) - if err != nil { - return 0, err - } + g.structMarshalUint(field, keyV, "32", ptr) keys++ case "uint16": - var err = g.structMarshalUint(field, keyV, "16", ptr) - if err != nil { - return 0, err - } + g.structMarshalUint(field, keyV, "16", ptr) keys++ case "uint8": - var err = g.structMarshalUint(field, keyV, "8", ptr) - if err != nil { - return 0, err - } + g.structMarshalUint(field, keyV, "8", ptr) keys++ case "float64": - var err = g.structMarshalFloat(field, keyV, "", ptr) - if err != nil { - return 0, err - } + g.structMarshalFloat(field, keyV, "", ptr) keys++ default: // if ident is already in our spec list @@ -164,14 +129,16 @@ func (g *Gen) structGenMarshalIdent(field *ast.Field, i *ast.Ident, keys int, pt func (g *Gen) structMarshalNonPrim(field *ast.Field, keyV string, sp *ast.TypeSpec, ptr bool) error { switch sp.Type.(type) { case *ast.StructType: - return g.structMarshalStruct(field, keyV, sp, ptr) + g.structMarshalStruct(field, keyV, sp, ptr) + return nil case *ast.ArrayType: - return g.structMarshalArr(field, keyV, sp, ptr) + g.structMarshalArr(field, keyV, sp, ptr) + return nil } return nil } -func (g *Gen) structMarshalString(field *ast.Field, keyV string, ptr bool) error { +func (g *Gen) structMarshalString(field *ast.Field, keyV string, ptr bool) { key := field.Names[0].String() ptrStr := "" if ptr { @@ -183,12 +150,11 @@ func (g *Gen) structMarshalString(field *ast.Field, keyV string, ptr bool) error Ptr string }{key, keyV, ptrStr}) if err != nil { - return err + log.Fatal(err) } - return nil } -func (g *Gen) structMarshalBool(field *ast.Field, keyV string, ptr bool) error { +func (g *Gen) structMarshalBool(field *ast.Field, keyV string, ptr bool) { key := field.Names[0].String() ptrStr := "" if ptr { @@ -200,12 +166,11 @@ func (g *Gen) structMarshalBool(field *ast.Field, keyV string, ptr bool) error { Ptr string }{key, keyV, ptrStr}) if err != nil { - return err + log.Fatal(err) } - return nil } -func (g *Gen) structMarshalInt(field *ast.Field, keyV string, intLen string, ptr bool) error { +func (g *Gen) structMarshalInt(field *ast.Field, keyV string, intLen string, ptr bool) { key := field.Names[0].String() ptrStr := "" if ptr { @@ -218,12 +183,11 @@ func (g *Gen) structMarshalInt(field *ast.Field, keyV string, intLen string, ptr Ptr string }{key, intLen, keyV, ptrStr}) if err != nil { - return err + log.Fatal(err) } - return nil } -func (g *Gen) structMarshalUint(field *ast.Field, keyV string, intLen string, ptr bool) error { +func (g *Gen) structMarshalUint(field *ast.Field, keyV string, intLen string, ptr bool) { key := field.Names[0].String() ptrStr := "" if ptr { @@ -236,12 +200,11 @@ func (g *Gen) structMarshalUint(field *ast.Field, keyV string, intLen string, pt Ptr string }{key, intLen, keyV, ptrStr}) if err != nil { - return err + log.Fatal(err) } - return nil } -func (g *Gen) structMarshalFloat(field *ast.Field, keyV string, intLen string, ptr bool) error { +func (g *Gen) structMarshalFloat(field *ast.Field, keyV string, intLen string, ptr bool) { key := field.Names[0].String() ptrStr := "" if ptr { @@ -254,12 +217,11 @@ func (g *Gen) structMarshalFloat(field *ast.Field, keyV string, intLen string, p Ptr string }{key, intLen, keyV, ptrStr}) if err != nil { - return err + log.Fatal(err) } - return nil } -func (g *Gen) structMarshalStruct(field *ast.Field, keyV string, st *ast.TypeSpec, ptr bool) error { +func (g *Gen) structMarshalStruct(field *ast.Field, keyV string, st *ast.TypeSpec, ptr bool) { key := field.Names[0].String() ptrStr := "" if ptr { @@ -271,12 +233,11 @@ func (g *Gen) structMarshalStruct(field *ast.Field, keyV string, st *ast.TypeSpe Ptr string }{keyV, key, ptrStr}) if err != nil { - return err + log.Fatal(err) } - return nil } -func (g *Gen) structMarshalArr(field *ast.Field, keyV string, st *ast.TypeSpec, ptr bool) error { +func (g *Gen) structMarshalArr(field *ast.Field, keyV string, st *ast.TypeSpec, ptr bool) { key := field.Names[0].String() ptrStr := "" if ptr { @@ -288,7 +249,6 @@ func (g *Gen) structMarshalArr(field *ast.Field, keyV string, st *ast.TypeSpec, Ptr string }{keyV, key, ptrStr}) if err != nil { - return err + log.Fatal(err) } - return nil } diff --git a/gojay/gen_struct_test.go b/gojay/gen_struct_test.go @@ -23,6 +23,9 @@ type Struct struct{ Int16 int16 Int32 int32 Int64 int64 + Uint8 uint8 + Uint16 uint16 + Uint32 uint32 Uint64 uint64 Float float64 Str string @@ -46,6 +49,12 @@ func (v *Struct) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { return dec.Int32(&v.Int32) case "int64": return dec.Int64(&v.Int64) + case "uint8": + return dec.Uint8(&v.Uint8) + case "uint16": + return dec.Uint16(&v.Uint16) + case "uint32": + return dec.Uint32(&v.Uint32) case "uint64": return dec.Uint64(&v.Uint64) case "float": @@ -59,7 +68,7 @@ func (v *Struct) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { } // NKeys returns the number of keys to unmarshal -func (v *Struct) NKeys() int { return 9 } +func (v *Struct) NKeys() int { return 12 } // MarshalJSONObject implements gojay's MarshalerJSONObject func (v *Struct) MarshalJSONObject(enc *gojay.Encoder) { @@ -68,6 +77,9 @@ func (v *Struct) MarshalJSONObject(enc *gojay.Encoder) { enc.Int16Key("int16", v.Int16) enc.Int32Key("int32", v.Int32) enc.Int64Key("int64", v.Int64) + enc.Uint8Key("uint8", v.Uint8) + enc.Uint16Key("uint16", v.Uint16) + enc.Uint32Key("uint32", v.Uint32) enc.Uint64Key("uint64", v.Uint64) enc.FloatKey("float", v.Float) enc.StringKey("str", v.Str) @@ -367,7 +379,11 @@ func (v *Struct) IsNil() bool { return v == nil } if err != nil { t.Fatal(err) } - assert.Equal(t, testCase.expectedResult, g.b.String()) + assert.Equal( + t, + string(genHeader)+testCase.expectedResult, + g.b.String(), + ) }) } } diff --git a/gojay/gen_struct_unmarshal.go b/gojay/gen_struct_unmarshal.go @@ -3,6 +3,7 @@ package main import ( "errors" "go/ast" + "log" ) var structUnmarshalSwitchOpen = []byte("\tswitch k {\n") @@ -75,76 +76,40 @@ func (g *Gen) structGenUnmarshalIdent(field *ast.Field, i *ast.Ident, keys int, switch i.String() { case "string": - var err = g.structUnmarshalString(field, keyV, ptr) - if err != nil { - return 0, err - } + g.structUnmarshalString(field, keyV, ptr) keys++ case "bool": - var err = g.structUnmarshalBool(field, keyV, ptr) - if err != nil { - return 0, err - } + g.structUnmarshalBool(field, keyV, ptr) keys++ case "int": - var err = g.structUnmarshalInt(field, keyV, "", ptr) - if err != nil { - return 0, err - } + g.structUnmarshalInt(field, keyV, "", ptr) keys++ case "int64": - var err = g.structUnmarshalInt(field, keyV, "64", ptr) - if err != nil { - return 0, err - } + g.structUnmarshalInt(field, keyV, "64", ptr) keys++ case "int32": - var err = g.structUnmarshalInt(field, keyV, "32", ptr) - if err != nil { - return 0, err - } + g.structUnmarshalInt(field, keyV, "32", ptr) keys++ case "int16": - var err = g.structUnmarshalInt(field, keyV, "16", ptr) - if err != nil { - return 0, err - } + g.structUnmarshalInt(field, keyV, "16", ptr) keys++ case "int8": - var err = g.structUnmarshalInt(field, keyV, "8", ptr) - if err != nil { - return 0, err - } + g.structUnmarshalInt(field, keyV, "8", ptr) keys++ case "uint64": - var err = g.structUnmarshalUint(field, keyV, "64", ptr) - if err != nil { - return 0, err - } + g.structUnmarshalUint(field, keyV, "64", ptr) keys++ case "uint32": - var err = g.structUnmarshalUint(field, keyV, "32", ptr) - if err != nil { - return 0, err - } + g.structUnmarshalUint(field, keyV, "32", ptr) keys++ case "uint16": - var err = g.structUnmarshalUint(field, keyV, "16", ptr) - if err != nil { - return 0, err - } + g.structUnmarshalUint(field, keyV, "16", ptr) keys++ case "uint8": - var err = g.structUnmarshalUint(field, keyV, "8", ptr) - if err != nil { - return 0, err - } + g.structUnmarshalUint(field, keyV, "8", ptr) keys++ case "float64": - var err = g.structUnmarshalFloat(field, keyV, "", ptr) - if err != nil { - return 0, err - } + g.structUnmarshalFloat(field, keyV, "", ptr) keys++ default: // if ident is already in our spec list @@ -176,20 +141,22 @@ func (g *Gen) structGenUnmarshalIdent(field *ast.Field, i *ast.Ident, keys int, func (g *Gen) structUnmarshalNonPrim(field *ast.Field, keyV string, sp *ast.TypeSpec, ptr bool) error { switch sp.Type.(type) { case *ast.StructType: - return g.structUnmarshalStruct(field, keyV, sp, ptr) + g.structUnmarshalStruct(field, keyV, sp, ptr) + return nil case *ast.ArrayType: - return g.structUnmarshalArr(field, keyV, sp, ptr) + g.structUnmarshalArr(field, keyV, sp, ptr) + return nil } return errors.New("Unknown type") } -func (g *Gen) structUnmarshalString(field *ast.Field, keyV string, ptr bool) error { +func (g *Gen) structUnmarshalString(field *ast.Field, keyV string, ptr bool) { key := field.Names[0].String() err := structUnmarshalTpl["case"].tpl.Execute(g.b, struct { Key string }{keyV}) if err != nil { - return err + log.Fatal(err) } if ptr { err = structUnmarshalTpl["string"].tpl.Execute(g.b, struct { @@ -197,7 +164,7 @@ func (g *Gen) structUnmarshalString(field *ast.Field, keyV string, ptr bool) err Ptr string }{key, ""}) if err != nil { - return err + log.Fatal(err) } } else { err = structUnmarshalTpl["string"].tpl.Execute(g.b, struct { @@ -205,19 +172,18 @@ func (g *Gen) structUnmarshalString(field *ast.Field, keyV string, ptr bool) err Ptr string }{key, "&"}) if err != nil { - return err + log.Fatal(err) } } - return nil } -func (g *Gen) structUnmarshalBool(field *ast.Field, keyV string, ptr bool) error { +func (g *Gen) structUnmarshalBool(field *ast.Field, keyV string, ptr bool) { key := field.Names[0].String() err := structUnmarshalTpl["case"].tpl.Execute(g.b, struct { Key string }{keyV}) if err != nil { - return err + log.Fatal(err) } if ptr { err = structUnmarshalTpl["bool"].tpl.Execute(g.b, struct { @@ -225,7 +191,7 @@ func (g *Gen) structUnmarshalBool(field *ast.Field, keyV string, ptr bool) error Ptr string }{key, ""}) if err != nil { - return err + log.Fatal(err) } } else { err = structUnmarshalTpl["bool"].tpl.Execute(g.b, struct { @@ -233,19 +199,18 @@ func (g *Gen) structUnmarshalBool(field *ast.Field, keyV string, ptr bool) error Ptr string }{key, "&"}) if err != nil { - return err + log.Fatal(err) } } - return nil } -func (g *Gen) structUnmarshalInt(field *ast.Field, keyV string, intLen string, ptr bool) error { +func (g *Gen) structUnmarshalInt(field *ast.Field, keyV string, intLen string, ptr bool) { key := field.Names[0].String() err := structUnmarshalTpl["case"].tpl.Execute(g.b, struct { Key string }{keyV}) if err != nil { - return err + log.Fatal(err) } if ptr { err = structUnmarshalTpl["int"].tpl.Execute(g.b, struct { @@ -254,7 +219,7 @@ func (g *Gen) structUnmarshalInt(field *ast.Field, keyV string, intLen string, p Ptr string }{key, intLen, ""}) if err != nil { - return err + log.Fatal(err) } } else { err = structUnmarshalTpl["int"].tpl.Execute(g.b, struct { @@ -263,19 +228,18 @@ func (g *Gen) structUnmarshalInt(field *ast.Field, keyV string, intLen string, p Ptr string }{key, intLen, "&"}) if err != nil { - return err + log.Fatal(err) } } - return nil } -func (g *Gen) structUnmarshalUint(field *ast.Field, keyV string, intLen string, ptr bool) error { +func (g *Gen) structUnmarshalUint(field *ast.Field, keyV string, intLen string, ptr bool) { key := field.Names[0].String() err := structUnmarshalTpl["case"].tpl.Execute(g.b, struct { Key string }{keyV}) if err != nil { - return err + log.Fatal(err) } if ptr { err = structUnmarshalTpl["uint"].tpl.Execute(g.b, struct { @@ -284,7 +248,7 @@ func (g *Gen) structUnmarshalUint(field *ast.Field, keyV string, intLen string, Ptr string }{key, intLen, ""}) if err != nil { - return err + log.Fatal(err) } } else { err = structUnmarshalTpl["uint"].tpl.Execute(g.b, struct { @@ -293,19 +257,18 @@ func (g *Gen) structUnmarshalUint(field *ast.Field, keyV string, intLen string, Ptr string }{key, intLen, "&"}) if err != nil { - return err + log.Fatal(err) } } - return nil } -func (g *Gen) structUnmarshalFloat(field *ast.Field, keyV string, intLen string, ptr bool) error { +func (g *Gen) structUnmarshalFloat(field *ast.Field, keyV string, intLen string, ptr bool) { key := field.Names[0].String() err := structUnmarshalTpl["case"].tpl.Execute(g.b, struct { Key string }{keyV}) if err != nil { - return err + log.Fatal(err) } if ptr { err = structUnmarshalTpl["float"].tpl.Execute(g.b, struct { @@ -314,7 +277,7 @@ func (g *Gen) structUnmarshalFloat(field *ast.Field, keyV string, intLen string, Ptr string }{key, intLen, ""}) if err != nil { - return err + log.Fatal(err) } } else { err = structUnmarshalTpl["float"].tpl.Execute(g.b, struct { @@ -323,19 +286,18 @@ func (g *Gen) structUnmarshalFloat(field *ast.Field, keyV string, intLen string, Ptr string }{key, intLen, "&"}) if err != nil { - return err + log.Fatal(err) } } - return nil } -func (g *Gen) structUnmarshalStruct(field *ast.Field, keyV string, st *ast.TypeSpec, ptr bool) error { +func (g *Gen) structUnmarshalStruct(field *ast.Field, keyV string, st *ast.TypeSpec, ptr bool) { key := field.Names[0].String() err := structUnmarshalTpl["case"].tpl.Execute(g.b, struct { Key string }{keyV}) if err != nil { - return err + log.Fatal(err) } if ptr { err = structUnmarshalTpl["structPtr"].tpl.Execute(g.b, struct { @@ -343,7 +305,7 @@ func (g *Gen) structUnmarshalStruct(field *ast.Field, keyV string, st *ast.TypeS StructName string }{key, st.Name.String()}) if err != nil { - return err + log.Fatal(err) } } else { err = structUnmarshalTpl["struct"].tpl.Execute(g.b, struct { @@ -351,26 +313,34 @@ func (g *Gen) structUnmarshalStruct(field *ast.Field, keyV string, st *ast.TypeS StructName string }{key, st.Name.String()}) if err != nil { - return err + log.Fatal(err) } } - return nil } -func (g *Gen) structUnmarshalArr(field *ast.Field, keyV string, st *ast.TypeSpec, ptr bool) error { +func (g *Gen) structUnmarshalArr(field *ast.Field, keyV string, st *ast.TypeSpec, ptr bool) { key := field.Names[0].String() err := structUnmarshalTpl["case"].tpl.Execute(g.b, struct { Key string }{keyV}) if err != nil { - return err + log.Fatal(err) } - err = structUnmarshalTpl["arr"].tpl.Execute(g.b, struct { - Field string - TypeName string - }{key, st.Name.String()}) - if err != nil { - return err + if ptr { + err = structUnmarshalTpl["arrPtr"].tpl.Execute(g.b, struct { + Field string + TypeName string + }{key, st.Name.String()}) + if err != nil { + log.Fatal(err) + } + } else { + err = structUnmarshalTpl["arr"].tpl.Execute(g.b, struct { + Field string + TypeName string + }{key, st.Name.String()}) + if err != nil { + log.Fatal(err) + } } - return nil } diff --git a/gojay/gen_struct_unmarshal_tpl.go b/gojay/gen_struct_unmarshal_tpl.go @@ -51,6 +51,14 @@ func (v *{{.StructName}}) NKeys() int { return {{.NKeys}} } return dec.Array(&v.{{.Field}}) `, }, + "arrPtr": &genTpl{ + strTpl: ` if v.{{.Field}} == nil { + arr := make({{.TypeName}}, 0) + v.{{.Field}} = &arr + } + return dec.Array(v.{{.Field}}) +`, + }, } func init() { diff --git a/gojay/gen_test.go b/gojay/gen_test.go @@ -8,13 +8,13 @@ import ( ) func MakeGenFromReader(input io.Reader) (*Gen, error) { - g := NewGen("") + g := NewGen("", []string{}) fset := token.NewFileSet() f, err := parser.ParseFile(fset, "", input, parser.ParseComments) if err != nil { return nil, err } - v := NewVisitor(g, g.pkg) + v := newVisitor(g, g.pkg) ast.Walk(v, f) if err != nil { return nil, err diff --git a/gojay/main.go b/gojay/main.go @@ -13,6 +13,7 @@ import ( var dst = flag.String("o", "", "destination file to output generated implementations") var src = flag.String("s", "", "source dir or file") +var types = flag.String("t", "", "types to generate") func hasAnnotation(fP string) bool { b, err := ioutil.ReadFile(fP) @@ -26,11 +27,16 @@ func hasAnnotation(fP string) bool { func getPath() (string, error) { var err error var p string - if *src != "" { + if *src != "" { // if src is present parse from src p, err = filepath.Abs(*src) if err != nil { return "", err } + } else if len(os.Args) > 1 { // else if there is a command line arg, use it as path to a package $GOPATH/src/os.Args[1] + p, err = filepath.Abs(os.Getenv("GOPATH") + "/src/" + os.Args[1]) + if err != nil { + return "", err + } } else { p, err = os.Getwd() if err != nil { @@ -40,15 +46,32 @@ func getPath() (string, error) { return p, nil } -func main() { +func getTypes() (t []string) { + if *types != "" { // if src is present parse from src + return strings.Split(*types, ",") + } else if *src == "" && *dst == "" && len(os.Args) > 2 { // else if there is a command line arg, use it as path to a package $GOPATH/src/os.Args[1] + return strings.Split(os.Args[2], ",") + } + return t +} + +func parseArgs() (p string, t []string, err error) { flag.Parse() - // get path - p, err := getPath() + p, err = getPath() + if err != nil { + return p, t, err + } + t = getTypes() + return p, t, err +} + +func main() { + p, t, err := parseArgs() if err != nil { log.Fatal(err) } // parse source files - g := NewGen(p) + g := NewGen(p, t) err = g.parse() if err != nil { log.Fatal(err) diff --git a/gojay/tests/complex_structs.go b/gojay/tests/complex_structs.go @@ -1 +0,0 @@ -package tests diff --git a/gojay/tests/json.go b/gojay/tests/json.go @@ -0,0 +1,284 @@ +// Code generated by GoJay. DO NOT EDIT. + +package tests + +import "github.com/francoispqt/gojay" + +// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray +func (v *StrSlice) UnmarshalJSONArray(dec *gojay.Decoder) error { + var str string + if err := dec.String(&str); err != nil { + return err + } + *v = append(*v, str) + return nil +} + +// MarshalJSONArray implements gojay's MarshalerJSONArray +func (v *StrSlice) MarshalJSONArray(enc *gojay.Encoder) { + for _, s := range *v { + enc.String(s) + } +} + +// IsNil implements gojay's MarshalerJSONArray +func (v *StrSlice) IsNil() bool { + return *v == nil || len(*v) == 0 +} + +// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray +func (v *IntSlice) UnmarshalJSONArray(dec *gojay.Decoder) error { + var i int + if err := dec.Int(&i); err != nil { + return err + } + *v = append(*v, i) + return nil +} + +// MarshalJSONArray implements gojay's MarshalerJSONArray +func (v *IntSlice) MarshalJSONArray(enc *gojay.Encoder) { + for _, s := range *v { + enc.Int(s) + } +} + +// IsNil implements gojay's MarshalerJSONArray +func (v *IntSlice) IsNil() bool { + return *v == nil || len(*v) == 0 +} + +// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray +func (v *BoolSlice) UnmarshalJSONArray(dec *gojay.Decoder) error { + var b bool + if err := dec.Bool(&b); err != nil { + return err + } + *v = append(*v, b) + return nil +} + +// MarshalJSONArray implements gojay's MarshalerJSONArray +func (v *BoolSlice) MarshalJSONArray(enc *gojay.Encoder) { + for _, s := range *v { + enc.Bool(s) + } +} + +// IsNil implements gojay's MarshalerJSONArray +func (v *BoolSlice) IsNil() bool { + return *v == nil || len(*v) == 0 +} + +// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray +func (v *StructSlice) UnmarshalJSONArray(dec *gojay.Decoder) error { + var s = &A{} + if err := dec.Object(s); err != nil { + return err + } + *v = append(*v, s) + return nil +} + +// MarshalJSONArray implements gojay's MarshalerJSONArray +func (v *StructSlice) MarshalJSONArray(enc *gojay.Encoder) { + for _, s := range *v { + enc.Object(s) + } +} + +// IsNil implements gojay's MarshalerJSONArray +func (v *StructSlice) IsNil() bool { + return *v == nil || len(*v) == 0 +} + +// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray +func (v *SliceSlice) UnmarshalJSONArray(dec *gojay.Decoder) error { + var s = make(StrSlice, 0) + if err := dec.Array(&s); err != nil { + return err + } + *v = append(*v, &s) + return nil +} + +// MarshalJSONArray implements gojay's MarshalerJSONArray +func (v *SliceSlice) MarshalJSONArray(enc *gojay.Encoder) { + for _, s := range *v { + enc.Array(s) + } +} + +// IsNil implements gojay's MarshalerJSONArray +func (v *SliceSlice) IsNil() bool { + return *v == nil || len(*v) == 0 +} + +// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject +func (v *A) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { + switch k { + case "string": + return dec.String(&v.Str) + case "bool": + return dec.Bool(&v.Bool) + case "int": + return dec.Int(&v.Int) + case "int64": + return dec.Int64(&v.Int64) + case "int32": + return dec.Int32(&v.Int32) + case "int16": + return dec.Int16(&v.Int16) + case "int8": + return dec.Int8(&v.Int8) + case "uint64": + return dec.Uint64(&v.Uint64) + case "uint32": + return dec.Uint32(&v.Uint32) + case "uint16": + return dec.Uint16(&v.Uint16) + case "uint8": + return dec.Uint8(&v.Uint8) + case "bval": + if v.Bval == nil { + v.Bval = &B{} + } + return dec.Object(v.Bval) + case "arrval": + if v.Arrval == nil { + arr := make(StrSlice, 0) + v.Arrval = &arr + } + return dec.Array(v.Arrval) + } + return nil +} + +// NKeys returns the number of keys to unmarshal +func (v *A) NKeys() int { return 13 } + +// MarshalJSONObject implements gojay's MarshalerJSONObject +func (v *A) MarshalJSONObject(enc *gojay.Encoder) { + enc.StringKey("string", v.Str) + enc.BoolKey("bool", v.Bool) + enc.IntKey("int", v.Int) + enc.Int64Key("int64", v.Int64) + enc.Int32Key("int32", v.Int32) + enc.Int16Key("int16", v.Int16) + enc.Int8Key("int8", v.Int8) + enc.Uint64Key("uint64", v.Uint64) + enc.Uint32Key("uint32", v.Uint32) + enc.Uint16Key("uint16", v.Uint16) + enc.Uint8Key("uint8", v.Uint8) + enc.ObjectKey("bval", v.Bval) + enc.ArrayKey("arrval", v.Arrval) +} + +// IsNil returns wether the structure is nil value or not +func (v *A) IsNil() bool { return v == nil } + +// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject +func (v *B) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { + switch k { + case "str": + return dec.String(&v.Str) + case "bool": + return dec.Bool(&v.Bool) + case "int": + return dec.Int(&v.Int) + case "int64": + return dec.Int64(&v.Int64) + case "int32": + return dec.Int32(&v.Int32) + case "int16": + return dec.Int16(&v.Int16) + case "int8": + return dec.Int8(&v.Int8) + case "uint64": + return dec.Uint64(&v.Uint64) + case "uint32": + return dec.Uint32(&v.Uint32) + case "uint16": + return dec.Uint16(&v.Uint16) + case "uint8": + return dec.Uint8(&v.Uint8) + case "strPtr": + return dec.String(v.StrPtr) + case "boolPtr": + return dec.Bool(v.BoolPtr) + case "intPtr": + return dec.Int(v.IntPtr) + case "int64Ptr": + return dec.Int64(v.Int64Ptr) + case "int32Ptr": + return dec.Int32(v.Int32Ptr) + case "int16Ptr": + return dec.Int16(v.Int16Ptr) + case "int8Ptr": + return dec.Int8(v.Int8Ptr) + case "uint64Ptr": + return dec.Uint64(v.Uint64Ptr) + case "uint32Ptr": + return dec.Uint32(v.Uint32Ptr) + case "uint16Ptr": + return dec.Uint16(v.Uint16Ptr) + case "uint8PTr": + return dec.Uint8(v.Uint8PTr) + } + return nil +} + +// NKeys returns the number of keys to unmarshal +func (v *B) NKeys() int { return 22 } + +// MarshalJSONObject implements gojay's MarshalerJSONObject +func (v *B) MarshalJSONObject(enc *gojay.Encoder) { + enc.StringKey("str", v.Str) + enc.BoolKey("bool", v.Bool) + enc.IntKey("int", v.Int) + enc.Int64Key("int64", v.Int64) + enc.Int32Key("int32", v.Int32) + enc.Int16Key("int16", v.Int16) + enc.Int8Key("int8", v.Int8) + enc.Uint64Key("uint64", v.Uint64) + enc.Uint32Key("uint32", v.Uint32) + enc.Uint16Key("uint16", v.Uint16) + enc.Uint8Key("uint8", v.Uint8) + enc.StringKey("strPtr", *v.StrPtr) + enc.BoolKey("boolPtr", *v.BoolPtr) + enc.IntKey("intPtr", *v.IntPtr) + enc.Int64Key("int64Ptr", *v.Int64Ptr) + enc.Int32Key("int32Ptr", *v.Int32Ptr) + enc.Int16Key("int16Ptr", *v.Int16Ptr) + enc.Int8Key("int8Ptr", *v.Int8Ptr) + enc.Uint64Key("uint64Ptr", *v.Uint64Ptr) + enc.Uint32Key("uint32Ptr", *v.Uint32Ptr) + enc.Uint16Key("uint16Ptr", *v.Uint16Ptr) + enc.Uint8Key("uint8PTr", *v.Uint8PTr) +} + +// IsNil returns wether the structure is nil value or not +func (v *B) IsNil() bool { return v == nil } + +// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject +func (v MapStringInt) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { + var i int + if err := dec.Int(&i); err != nil { + return err + } + v[k] = i + return nil +} + +// NKeys returns the number of keys to unmarshal +func (v MapStringInt) NKeys() int { return 0 } + +// MarshalJSONObject implements gojay's MarshalerJSONObject +func (v MapStringInt) MarshalJSONObject(enc *gojay.Encoder) { + for k, s := range v { + enc.IntKey(k, s) + } +} + +// IsNil returns wether the structure is nil value or not +func (v MapStringInt) IsNil() bool { return v == nil || len(v) == 0 } diff --git a/gojay/tests/maps.go b/gojay/tests/maps.go @@ -0,0 +1,4 @@ +package tests + +//gojay:json +type MapStringInt map[string]int diff --git a/gojay/tests/basic_slices.go b/gojay/tests/slices.go diff --git a/gojay/tests/basic_structs.go b/gojay/tests/structs.go diff --git a/gojay/visitor.go b/gojay/visitor.go @@ -29,12 +29,12 @@ func (v *vis) Visit(n ast.Node) (w ast.Visitor) { v.commentFound = false return v case *ast.GenDecl: - if n.Doc != nil { + if len(v.g.types) == 0 && n.Doc != nil { v.commentFound = docContains(n.Doc, gojayAnnotation) } return v case *ast.TypeSpec: - if v.commentFound { + if v.commentFound || v.g.isGenType(n.Name.Name) { v.g.genTypes[n.Name.Name] = n } v.commentFound = false @@ -46,7 +46,7 @@ func (v *vis) Visit(n ast.Node) (w ast.Visitor) { return v } -func NewVisitor(g *Gen, pkgName string) *vis { +func newVisitor(g *Gen, pkgName string) *vis { return &vis{ g: g, pkg: pkgName,