commit 64fc2cdddab0ecee09ec942b9405acb17ee7e2dd
parent 7a748baed1f1ad343517effd3bf5a9c9fc64bf85
Author: Francois Parquet <francois.parquet@gmail.com>
Date: Sun, 17 Mar 2019 23:57:32 +0800
Merge pull request #101 from francoispqt/feature/replace-generator
Feature/replace generator
Diffstat:
89 files changed, 3149 insertions(+), 8133 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,4 +1,5 @@
+vendor
*.out
*.log
*.test
-.vscode
-\ No newline at end of file
+.vscode
diff --git a/.travis.yml b/.travis.yml
@@ -6,9 +6,10 @@ go:
- master
script:
- - go get github.com/stretchr/testify
- - go test ./gojay -race
+ - go get github.com/golang/dep/cmd/dep github.com/stretchr/testify
+ - dep ensure -v -vendor-only
+ - go test ./gojay/codegen/test/... -race
- go test -race -coverprofile=coverage.txt -covermode=atomic
after_success:
- - bash <(curl -s https://codecov.io/bash)
-\ No newline at end of file
+ - bash <(curl -s https://codecov.io/bash)
diff --git a/Gopkg.lock b/Gopkg.lock
@@ -2,20 +2,20 @@
[[projects]]
- digest = "1:a639b30711f62030ade1432a6bcf135c23c38607d1478d3ce53829ea2a664197"
+ digest = "1:3de22f0e7208f2e7fb8662fcab0aee360e3cae85d5f3649f3bf0b247f575d183"
name = "cloud.google.com/go"
packages = ["compute/metadata"]
pruneopts = ""
- revision = "0ebda48a7f143b1cce9eb37a8c1106ac762a3430"
- version = "v0.34.0"
+ revision = "f52f9bc132541d2aa914f42100c36d10b1ef7e0c"
+ version = "v0.37.0"
[[projects]]
- digest = "1:f7ad09e1bd153d7de18080ccd5e7bef5ebdba9403aa3cde487f0daf7ef67820d"
- name = "github.com/fatih/structtag"
- packages = ["."]
+ digest = "1:0deddd908b6b4b768cfc272c16ee61e7088a60f7fe2f06c547bd3d8e1f8b8e77"
+ name = "github.com/davecgh/go-spew"
+ packages = ["spew"]
pruneopts = ""
- revision = "76ae1d6d2117609598c7d4e8f3e938145f204e8f"
- version = "v1.0.0"
+ revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
+ version = "v1.1.1"
[[projects]]
digest = "1:968d8903d598e3fae738325d3410f33f07ea6a2b9ee5591e9c262ee37df6845a"
@@ -26,16 +26,16 @@
version = "v1.0.1"
[[projects]]
- digest = "1:3dd078fda7500c341bc26cfbc6c6a34614f295a2457149fc1045cab767cbcf18"
+ digest = "1:529d738b7976c3848cae5cf3a8036440166835e389c1f617af701eeb12a0518d"
name = "github.com/golang/protobuf"
packages = ["proto"]
pruneopts = ""
- revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
- version = "v1.2.0"
+ revision = "b5d812f8a3706043e23a9cd5babf2e5423744d30"
+ version = "v1.3.1"
[[projects]]
branch = "master"
- digest = "1:212bebc561f4f654a653225868b2a97353cd5e160dc0b0bbc7232b06608474ec"
+ digest = "1:b7ac1ad7d98781c0168803a258d7bf8b3544fd59f356a0e2dd65c43312cf6aac"
name = "github.com/mailru/easyjson"
packages = [
".",
@@ -44,7 +44,7 @@
"jwriter",
]
pruneopts = ""
- revision = "60711f1a8329503b04e1c88535f419d0bb440bff"
+ revision = "1de009706dbeb9d05f18586f0735fcdb7c524481"
[[projects]]
digest = "1:1d7e1867c49a6dd9856598ef7c3123604ea3daabf5b83f303ff457bcbc410b1d"
@@ -55,15 +55,15 @@
version = "v0.8.1"
[[projects]]
- digest = "1:63af8a601bded721d750a90c29bd3e0f760d78f3e24b4d464ed1390f2b18e8d4"
+ digest = "1:f6848760d34f35b10268f8aa3862181c19b4855dc0578a7b7144dc30e6f980f1"
name = "github.com/viant/assertly"
packages = ["."]
pruneopts = ""
- revision = "43698254226bcf31ac1b1283bc9be5d6db553f8e"
- version = "v0.3.0"
+ revision = "3810e26d53c2543cb1024e6287fc2a66814f6764"
+ version = "v0.4.4"
[[projects]]
- digest = "1:3e18fb0fe710202b9c43173c899175dc1bddb044dda2be257a3b961a836a1a14"
+ digest = "1:d9fb8cbd3cd93ee1d7358a060c0dcd6f737032f5261bf0185eb7e025066eb7c0"
name = "github.com/viant/toolbox"
packages = [
".",
@@ -73,12 +73,12 @@
"url",
]
pruneopts = ""
- revision = "a7e3c8c3c49e598d5f2ba1d4ca7e4694a9b7919b"
- version = "v0.9.0"
+ revision = "ead0bb31abed8480acfa8b80792d94593500d34b"
+ version = "v0.19.1"
[[projects]]
branch = "master"
- digest = "1:59b49c47c11a48f1054529207f65907c014ecf5f9a7c0d9c0f1616dec7b062ed"
+ digest = "1:ab3e9a81a5ec54c5d1ed41d0d6898ba88c6799fa401b784b06bdee8e432d872b"
name = "golang.org/x/crypto"
packages = [
"blowfish",
@@ -91,11 +91,11 @@
"ssh",
]
pruneopts = ""
- revision = "ff983b9c42bc9fbf91556e191cc8efb585c16908"
+ revision = "a1f597ede03a7bef967a422b5b3a5bd08805a01e"
[[projects]]
branch = "master"
- digest = "1:7ec13687f85b25087fe05f6ea8dd116013a8263f8eb7e057da7664bc7599d2d4"
+ digest = "1:73e6624a8569db94b0d8f9b34052f73ef9598c380edbce36d89dbbc00941e976"
name = "golang.org/x/net"
packages = [
"context",
@@ -103,11 +103,11 @@
"websocket",
]
pruneopts = ""
- revision = "915654e7eabcea33ae277abbecf52f0d8b7a9fdc"
+ revision = "9f648a60d9775ef5c977e7669d1673a7a67bef33"
[[projects]]
branch = "master"
- digest = "1:f059b0adae6e4630f111d471f127fe69de1f5689ce35465bab387d646c17eb97"
+ digest = "1:ffae4a89b63a2c845533a393b3340f8696898b11b71da1b187f82f08135c23a0"
name = "golang.org/x/oauth2"
packages = [
".",
@@ -117,7 +117,18 @@
"jwt",
]
pruneopts = ""
- revision = "5dab4167f31cbd76b407f1486c86b40748bc5073"
+ revision = "e64efc72b421e893cbf63f17ba2221e7d6d0b0f3"
+
+[[projects]]
+ branch = "master"
+ digest = "1:9f5e388a2e01d646e82dc420469e21a6e0e7a526954ef1638009bc87eacf578e"
+ name = "golang.org/x/sys"
+ packages = [
+ "cpu",
+ "unix",
+ ]
+ pruneopts = ""
+ revision = "a2f829d7f35f2ed1c3520c553a6226495455cae0"
[[projects]]
digest = "1:bc09e719c4e2a15d17163f5272d9a3131c45d77542b7fdc53ff518815bc19ab3"
@@ -150,7 +161,7 @@
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
- "github.com/fatih/structtag",
+ "github.com/davecgh/go-spew/spew",
"github.com/go-errors/errors",
"github.com/mailru/easyjson",
"github.com/mailru/easyjson/jlexer",
diff --git a/codegen/README.md b/codegen/README.md
@@ -1,61 +0,0 @@
-# Gojay code generator
-This package provides a command line tool to generate gojay's marshaling and unmarshing interface implementation for custom type(s)
-
-
-## Get started
-
-```sh
-go install github.com/francoispqt/gojay/gojaygen
-```
-
-## Generate code
-
-### Basic command
-The basic command is straightforward and easy to use:
-```sh
-cd $GOPATH/src/mycoany/myproject
-gojaygen -p myproject
-```
-If you just want to the output to stdout, omit the third parameter.
-
-### Using flags
-- s file/dir path, can be a relative or absolute path
-- t root types to generate with all its dependencies (comma separated)
-- a annotation tag used to read meta data (default: json)
-- o output file (relative or absolute path)
-- p reuse object witt sync.Pool
-
-Examples:
-
-- Specific type in a go package, write to a file:
-```sh
-gojay -s /tmp/myproj -t SomeType -o output.go
-```
-
-- Specific types in a file, with custom tag, write to stdout
-```sh
-gojay -s somegofile.go -a gojay -t SomeType
-```
-
-
-## Generator tags
-You can add tags to your structs to control:
-
-- the JSON key
-- skip a struct field
-- the use of omitempty methods for marshaling
-- timeFormat (java style data format)
-- timeLayout (golang time layout)
-
-
-### Example:
-```go
-type A struct {
- Str string `json:"string"`
- StrOmitEmpty string `json:"stringOrEmpty,omitempty"`
- Skip string `json:"-"`
- StartTime time.Time `json:"startDate" timeFormat:"yyyy-MM-dd HH:mm:ss"`
- EndTime *time.Time `json:"endDate" timeLayout:"2006-01-02 15:04:05"`
-}
-```
-
diff --git a/codegen/field.go b/codegen/field.go
@@ -1,161 +0,0 @@
-package codegen
-
-import (
- "fmt"
- "github.com/viant/toolbox"
- "strings"
-)
-
-//Field represents a field.
-type Field struct {
- Key string
- Init string
- OmitEmpty string
- TimeLayout string
- Name string
- Accessor string
- Mutator string
- Receiver string //alias and type name
- Alias string //object alias name
- Var string //variable for this field
- Type string
- RawType string
- HelperType string
- ComponentType string
- RawComponentType string
- IsPointerComponent bool
-
- PointerModifier string //takes field pointer, "&" if field is not a pointer type
- DereferenceModifier string //take pointer value, i.e "*" if field has a pointer type
-
- ComponentPointerModifier string //takes item pointer if needed,i.e
- ComponentDereferenceModifier string //de reference value if needed, i.e
- ComponentInitModifier string //takes item pointer if type is not a pointer type
- ComponentInit string //initialises component type
-
- DecodingMethod string
- EncodingMethod string
- PoolName string //pool name associated with this field
- ResetDependency string
- Reset string
- IsAnonymous bool
- IsPointer bool
- IsSlice bool
-}
-
-//NewField returns a new field
-func NewField(owner *Struct, field *toolbox.FieldInfo, fieldType *toolbox.TypeInfo) (*Field, error) {
- typeName := normalizeTypeName(field.TypeName)
- var result = &Field{
- IsAnonymous: field.IsAnonymous,
- Name: field.Name,
- RawType: field.TypeName,
- IsPointer: field.IsPointer,
- Key: getJSONKey(owner.options, field),
- Receiver: owner.Alias + " *" + owner.TypeInfo.Name,
- Type: typeName,
- Mutator: owner.Alias + "." + field.Name,
- Accessor: owner.Alias + "." + field.Name,
- ComponentType: field.ComponentType,
- IsPointerComponent: field.IsPointerComponent,
- Var: firstLetterToLowercase(field.Name),
- Init: fmt.Sprintf("%v{}", typeName),
- TimeLayout: "time.RFC3339",
- IsSlice: field.IsSlice,
- PoolName: getPoolName(field.TypeName),
- Alias: owner.Alias,
- Reset: "nil",
- }
- var err error
- if field.IsPointer {
- result.DereferenceModifier = "*"
- result.Init = "&" + result.Init
- } else {
- result.PointerModifier = "&"
-
- }
- if field.IsSlice {
- result.HelperType = getSliceHelperTypeName(field.ComponentType, field.IsPointerComponent)
- result.PoolName = getPoolName(field.ComponentType)
- } else if fieldType != nil {
- result.HelperType = getSliceHelperTypeName(fieldType.Name, field.IsPointerComponent)
- }
-
- if options := getTagOptions(field.Tag, "timeLayout"); len(options) > 0 {
- result.TimeLayout = wrapperIfNeeded(options[0], `"`)
- } else if options := getTagOptions(field.Tag, "timeFormat"); len(options) > 0 {
- result.TimeLayout = wrapperIfNeeded(toolbox.DateFormatToLayout(options[0]), `"`)
- }
- if strings.Contains(field.Tag, "omitEmpty") {
- result.OmitEmpty = "OmitEmpty"
- }
- if owner.options.PoolObjects {
- if field.IsPointer && !strings.HasSuffix(field.TypeName, ".Time") {
- poolName := getPoolName(field.TypeName)
- result.Init = fmt.Sprintf(`%v.Get().(*%v)`, poolName, field.TypeName)
- }
- }
-
- encodingMethod := field.ComponentType
- if encodingMethod == "" {
- encodingMethod = result.Type
- }
- result.DecodingMethod = firstLetterToUppercase(encodingMethod)
- result.EncodingMethod = firstLetterToUppercase(encodingMethod)
-
- switch typeName {
- case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64":
- result.Reset = "0"
- case "float32", "float64":
- result.Reset = "0.0"
- case "string":
- result.Reset = `""`
-
- case "bool":
- result.Reset = "false"
- default:
- if field.IsSlice && owner.Type(field.ComponentType) != nil {
- var itemPointer = ""
- if !field.IsPointerComponent {
- itemPointer = "&"
- }
- result.ResetDependency, err = expandFieldTemplate(poolSliceInstanceRelease, struct {
- PoolName string
- Accessor string
- PointerModifier string
- }{PoolName: result.PoolName, Accessor: result.Accessor, PointerModifier: itemPointer})
- if err != nil {
- return nil, err
- }
-
- } else if field.IsPointer && fieldType != nil {
- result.ResetDependency, err = expandFieldTemplate(poolInstanceRelease, struct {
- PoolName string
- Accessor string
- }{PoolName: result.PoolName, Accessor: result.Accessor})
- if err != nil {
- return nil, err
- }
- }
-
- }
- if field.IsSlice || field.IsPointer {
- result.Reset = "nil"
- }
-
- if result.IsPointerComponent {
- result.ComponentInit = "&" + result.ComponentType + "{}"
- result.RawComponentType = "*" + result.ComponentType
-
- result.ComponentDereferenceModifier = "*"
- result.ComponentInitModifier = "&"
-
- } else {
- result.ComponentInit = result.ComponentType + "{}"
- result.RawComponentType = result.ComponentType
-
- result.ComponentPointerModifier = "&"
- }
-
- return result, nil
-}
diff --git a/codegen/generator.go b/codegen/generator.go
@@ -1,167 +0,0 @@
-package codegen
-
-import (
- "fmt"
- "github.com/viant/toolbox"
- "io/ioutil"
- "strings"
-)
-
-type Generator struct {
- fileInfo *toolbox.FileSetInfo
- types map[string]string
- structTypes map[string]string
- sliceTypes map[string]string
- pooledObjects map[string]string
- poolInit map[string]string
- imports map[string]bool
- filedInit []string
- Pkg string
- Code string
- Init string
- Imports string
- options *Options
-}
-
-func (g *Generator) Type(typeName string) *toolbox.TypeInfo {
- return g.fileInfo.Type(typeName)
-}
-
-func (g *Generator) addImport(pkg string) {
- g.imports[`"`+pkg+`"`] = true
-}
-
-func (g *Generator) init() {
- g.filedInit = []string{}
- g.imports = map[string]bool{}
- g.pooledObjects = map[string]string{}
- g.structTypes = map[string]string{}
- g.sliceTypes = map[string]string{}
- g.poolInit = map[string]string{}
- g.addImport("github.com/francoispqt/gojay")
-}
-
-func (g *Generator) Generate(options *Options) error {
- if err := options.Validate(); err != nil {
- return err
- }
- g.options = options
- g.init()
-
- if options.PoolObjects {
- g.addImport("sync")
- }
- if err := g.readPackageCode(options.Source); err != nil {
- return err
- }
- for _, rootType := range options.Types {
- if err := g.generateStructCode(rootType); err != nil {
- return err
- }
- }
- g.Imports = strings.Join(toolbox.MapKeysToStringSlice(g.imports), "\n")
- return g.writeCode()
-}
-
-func (g *Generator) writeCode() error {
- var generatedCode = []string{}
- for _, code := range g.pooledObjects {
- generatedCode = append(generatedCode, code)
- }
- generatedCode = append(generatedCode, "")
- for _, code := range g.sliceTypes {
- generatedCode = append(generatedCode, code)
- }
- generatedCode = append(generatedCode, "")
- for _, code := range g.structTypes {
- generatedCode = append(generatedCode, code)
- }
-
- for _, code := range g.poolInit {
- if g.Init != "" {
- g.Init += "\n"
- }
- g.Init += code
- }
- g.Code = strings.Join(generatedCode, "\n")
-
- expandedCode, err := expandBlockTemplate(fileCode, g)
- if err != nil {
- return err
- }
- if g.options.Dest == "" {
- fmt.Print(expandedCode)
- return nil
- }
- return ioutil.WriteFile(g.options.Dest, []byte(expandedCode), 0644)
-}
-
-func (g *Generator) generatePrimitiveArray(field *Field) error {
- key := field.ComponentType + toolbox.AsString(field.IsPointerComponent)
- if _, ok := g.sliceTypes[key]; ok {
- return nil
- }
- code, err := expandBlockTemplate(baseTypeSlice, field)
- g.sliceTypes[key] = code
- return err
-}
-
-func (g *Generator) generateObjectArray(field *Field) error {
- if _, ok := g.sliceTypes[field.RawComponentType]; ok {
- return nil
- }
-
- if err := g.generateStructCode(field.ComponentType); err != nil {
- return err
- }
- code, err := expandBlockTemplate(structTypeSlice, field)
- if err != nil {
- return err
- }
- g.sliceTypes[field.RawComponentType] = code
- return err
-}
-
-func (g *Generator) generatePool(structType string) error {
- if !g.options.PoolObjects {
- return nil
- }
- var err error
- if g.pooledObjects[structType], err = expandBlockTemplate(poolVar, struct {
- PoolName string
- }{getPoolName(structType)}); err == nil {
- g.poolInit[structType], err = expandBlockTemplate(poolInit, struct {
- PoolName string
- Type string
- }{getPoolName(structType), structType})
- }
- return err
-
-}
-
-func (g *Generator) generateStructCode(structType string) error {
- structType = normalizeTypeName(structType)
- typeInfo := g.Type(structType)
- if typeInfo == nil {
- return nil
- }
- if _, hasCode := g.structTypes[structType]; hasCode {
- return nil
- }
- g.generatePool(structType)
- aStruct := NewStruct(typeInfo, g)
- code, err := aStruct.Generate()
- if err != nil {
- return err
- }
- g.structTypes[structType] = code
- return nil
-}
-
-func (g *Generator) readPackageCode(pkgPath string) error {
- var err error
- fragments := strings.Split(pkgPath, "/")
- g.Pkg = fragments[len(fragments)-1]
- g.fileInfo, err = toolbox.NewFileSetInfo(pkgPath)
- return err
-}
diff --git a/codegen/generator_test.go b/codegen/generator_test.go
@@ -1,72 +0,0 @@
-package codegen
-
-import (
- "github.com/stretchr/testify/assert"
- "github.com/viant/toolbox"
- "log"
- "path"
- "testing"
-)
-
-func TestGenerator_Generate(t *testing.T) {
-
- parent := path.Join(toolbox.CallerDirectory(3), "test")
-
- var useCases = []struct {
- description string
- options *Options
- hasError bool
- }{
- {
- description: "basic struct code generation",
- options: &Options{
- Source: path.Join(parent, "basic_struct"),
- Types: []string{"Message"},
- Dest: path.Join(parent, "basic_struct", "encoding.go"),
- },
- },
-
- {
- description: "struct with pool code generation",
- options: &Options{
- Source: path.Join(parent, "pooled_struct"),
- Types: []string{"Message"},
- Dest: path.Join(parent, "pooled_struct", "encoding.go"),
- PoolObjects: true,
- },
- },
- {
- description: "struct with embedded type code generation",
- options: &Options{
- Source: path.Join(parent, "embedded_struct"),
- Types: []string{"Message"},
- Dest: path.Join(parent, "embedded_struct", "encoding.go"),
- PoolObjects: false,
- },
- },
- {
- description: "struct with json annotation and time/foarmat|layouat generation",
- options: &Options{
- Source: path.Join(parent, "annotated_struct"),
- Types: []string{"Message"},
- Dest: path.Join(parent, "annotated_struct", "encoding.go"),
- PoolObjects: false,
- TagName: "json",
- },
- },
- }
-
- for _, useCase := range useCases {
- gen := &Generator{}
- err := gen.Generate(useCase.options)
- if useCase.hasError {
- assert.NotNil(t, err, useCase.description)
- continue
- }
- if !assert.Nil(t, err, useCase.description) {
- log.Fatal(err)
- continue
- }
- }
-
-}
diff --git a/codegen/helper.go b/codegen/helper.go
@@ -1,88 +0,0 @@
-package codegen
-
-import (
- "github.com/viant/toolbox"
- "reflect"
- "strings"
-)
-
-func firstLetterToUppercase(text string) string {
- return strings.ToUpper(string(text[0:1])) + string(text[1:])
-}
-
-func firstLetterToLowercase(text string) string {
- return strings.ToLower(string(text[0:1])) + string(text[1:])
-}
-
-func extractReceiverAlias(structType string) string {
- var result = string(structType[0])
- for i := len(structType) - 1; i > 0; i-- {
- aChar := string(structType[i])
- lowerChar := strings.ToLower(aChar)
- if lowerChar != aChar {
- result = lowerChar
- break
- }
- }
- return strings.ToLower(result)
-}
-
-func getTagOptions(tag, key string) []string {
- if tag == "" {
- return nil
- }
- var structTag = reflect.StructTag(strings.Replace(tag, "`", "", len(tag)))
- options, ok := structTag.Lookup(key)
- if !ok {
- return nil
- }
- return strings.Split(options, ",")
-}
-
-func getSliceHelperTypeName(typeName string, isPointer bool) string {
- if typeName == "" {
- return ""
- }
- var pluralName = firstLetterToUppercase(typeName) + "s"
- if isPointer {
- pluralName += "Ptr"
- }
- return pluralName
-}
-
-func isSkipable(options *Options, field *toolbox.FieldInfo) bool {
- if options := getTagOptions(field.Tag, options.TagName); len(options) > 0 {
- for _, candidate := range options {
- if candidate == "-" {
- return true
- }
- }
- }
- return false
-}
-
-func wrapperIfNeeded(text, wrappingChar string) string {
- if strings.HasPrefix(text, wrappingChar) {
- return text
- }
- return wrappingChar + text + wrappingChar
-}
-
-func getPoolName(typeName string) string {
- typeName = strings.Replace(typeName, "*", "", 1)
- return typeName + "Pool"
-}
-
-func getJSONKey(options *Options, field *toolbox.FieldInfo) string {
- var key = field.Name
- if field.Tag != "" {
- if options := getTagOptions(field.Tag, options.TagName); len(options) > 0 {
- key = options[0]
- }
- }
- return key
-}
-
-func normalizeTypeName(typeName string) string {
- return strings.Replace(typeName, "*", "", strings.Count(typeName, "*"))
-}
diff --git a/codegen/options.go b/codegen/options.go
@@ -1,51 +0,0 @@
-package codegen
-
-import (
- "flag"
- "github.com/go-errors/errors"
- "github.com/viant/toolbox"
- "github.com/viant/toolbox/url"
- "strings"
-)
-
-type Options struct {
- Source string
- Dest string
- Types []string
- PoolObjects bool
- TagName string
-}
-
-func (o *Options) Validate() error {
- if o.Source == "" {
- return errors.New("Source was empty")
- }
- if len(o.Types) == 0 {
- return errors.New("Types was empty")
- }
- return nil
-}
-
-const (
- optionKeySource = "s"
- optionKeyDest = "o"
- optionKeyTypes = "t"
- optionKeyTagName = "a"
- optionKeyPoolObjects = "p"
-)
-
-//NewOptionsWithFlagSet creates a new options for the supplide flagset
-func NewOptionsWithFlagSet(set *flag.FlagSet) *Options {
- toolbox.Dump(set)
-
- var result = &Options{}
- result.Dest = set.Lookup(optionKeyDest).Value.String()
- result.Source = set.Lookup(optionKeySource).Value.String()
- result.PoolObjects = toolbox.AsBoolean(set.Lookup(optionKeyPoolObjects).Value.String())
- result.TagName = set.Lookup(optionKeyTagName).Value.String()
- result.Types = strings.Split(set.Lookup(optionKeyTypes).Value.String(), ",")
- if result.Source == "" {
- result.Source = url.NewResource(".").ParsedURL.Path
- }
- return result
-}
diff --git a/codegen/struct.go b/codegen/struct.go
@@ -1,296 +0,0 @@
-package codegen
-
-import (
- "fmt"
- "github.com/viant/toolbox"
- "strings"
-)
-
-type Struct struct {
- *toolbox.TypeInfo
- referenced *toolbox.TypeInfo
- *Generator
- Alias string
- Init string
- Body string
-}
-
-//Generate generates decoderCode + structRelease + encoderCode
-func (s *Struct) Generate() (string, error) {
- return s.generateEncoding(s.TypeInfo)
-}
-
-func (s *Struct) generateEncoding(structInfo *toolbox.TypeInfo) (string, error) {
- var initEmbedded, decodingCases, err = s.generateFieldDecoding(structInfo.Fields())
- if err != nil {
- return "", err
- }
-
- encodingCases, err := s.generateFieldEncoding(structInfo.Fields())
- if err != nil {
- return "", err
- }
- var resetCode = ""
- if s.options.PoolObjects {
- resetCode, err = s.generateReset(structInfo.Fields())
- if err != nil {
- return "", err
- }
- }
- var data = struct {
- Receiver string
- Alias string
- InitEmbedded string
- EncodingCases string
- DecodingCases string
- Reset string
- FieldCount int
- }{
- Receiver: s.Alias + " *" + s.Name,
- DecodingCases: strings.Join(decodingCases, "\n"),
- EncodingCases: strings.Join(encodingCases, "\n"),
- FieldCount: len(decodingCases),
- InitEmbedded: initEmbedded,
- Reset: resetCode,
- Alias: s.Alias,
- }
- return expandBlockTemplate(encodingStructType, data)
-}
-
-func (s *Struct) generateReset(fields []*toolbox.FieldInfo) (string, error) {
- fieldReset, err := s.generateFieldReset(fields)
- if err != nil {
- return "", nil
- }
- return expandBlockTemplate(resetStruct, struct {
- Reset string
- Receiver string
- }{
- Reset: strings.Join(fieldReset, "\n"),
- Receiver: s.Alias + " *" + s.Name,
- })
-}
-
-func (s *Struct) generateFieldReset(fields []*toolbox.FieldInfo) ([]string, error) {
- fieldReset := []string{}
- for i := range fields {
- var templateKey = -1
- fieldTypeInfo := s.Type(normalizeTypeName(fields[i].TypeName))
- field, err := NewField(s, fields[i], fieldTypeInfo)
- if err != nil {
- return nil, err
- }
- if field.IsPointer || field.IsSlice || (fieldTypeInfo != nil && fieldTypeInfo.IsSlice) {
- templateKey = resetFieldValue
- } else {
- switch field.Type {
- case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64", "string", "bool", "[]string", "[]bool", "[]int", "[]int8", "[]int16", "[]int32", "[]int64", "[]uint", "[]uint8", "[]uint16", "[]uint32", "[]uint64", "[]float32", "[]float64", "[]byte":
- templateKey = resetFieldValue
- }
- }
- if templateKey != -1 {
- code, err := expandFieldTemplate(templateKey, field)
- if err != nil {
- return nil, err
- }
- fieldReset = append(fieldReset, code)
- }
- }
- return fieldReset, nil
-}
-
-func (s *Struct) generateFieldDecoding(fields []*toolbox.FieldInfo) (string, []string, error) {
- fieldCases := []string{}
- var initCode = ""
- for i := range fields {
- if isSkipable(s.options, fields[i]) {
- continue
- }
- var templateKey = -1
- fieldTypeInfo := s.Type(normalizeTypeName(fields[i].TypeName))
- field, err := NewField(s, fields[i], fieldTypeInfo)
- if err != nil {
- return "", nil, err
- }
- if fieldTypeInfo != nil {
- if err = s.generateStructCode(fieldTypeInfo.Name); err != nil {
- return "", nil, err
- }
- }
-
- if field.IsAnonymous {
- if fieldTypeInfo != nil {
- if field.IsPointer {
- init, err := expandBlockTemplate(embeddedStructInit, field)
- if err != nil {
- return "", nil, err
- }
- initCode += init
- }
- init, embeddedCases, err := s.generateFieldDecoding(fieldTypeInfo.Fields())
- if err != nil {
- return "", nil, err
- }
- initCode += init
- fieldCases = append(fieldCases, embeddedCases...)
- }
- continue
- }
-
- main:
- switch field.Type {
- case "string", "bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64":
- templateKey = decodeBaseType
- case "[]string", "[]bool", "[]int", "[]int8", "[]int16", "[]int32", "[]int64", "[]uint", "[]uint8", "[]uint16", "[]uint32", "[]uint64", "[]float32", "[]float64":
- templateKey = decodeBaseTypeSlice
- s.generatePrimitiveArray(field)
- case "[]byte":
- templateKey = decodeRawType
- default:
-
- if fieldTypeInfo != nil {
- if !(field.IsSlice || fieldTypeInfo.IsSlice) {
-
- templateKey = decodeStruct
- break main
- }
-
- switch fieldTypeInfo.ComponentType {
- case "byte":
- templateKey = decodeRawType
- break main
-
- case "string", "bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64":
- s.generatePrimitiveArray(field)
- templateKey = decodeBaseTypeSlice
- break main
-
- }
-
- if err = s.generateStructCode(field.ComponentType); err != nil {
- return "", nil, err
- }
-
- templateKey = decodeStructSlice
- if err = s.generateObjectArray(field); err != nil {
- return "", nil, err
- }
-
- break main
- } else if field.IsSlice {
- templateKey = decodeStructSlice
- if err = s.generateObjectArray(field); err != nil {
- return "", nil, err
- }
-
- } else if strings.HasSuffix(field.Type, "time.Time") {
- templateKey = decodeTime
- s.addImport("time")
- } else {
- templateKey = decodeUnknown
- }
- }
- if templateKey != -1 {
- decodingCase, err := expandFieldTemplate(templateKey, field)
- if err != nil {
- return "", nil, err
- }
- fieldCases = append(fieldCases, decodingCase)
- }
-
- }
- return initCode, fieldCases, nil
-}
-
-func (s *Struct) generateEmbeddedFieldEncoding(field *Field, fieldTypeInfo *toolbox.TypeInfo) ([]string, error) {
- var result = []string{}
- if fieldTypeInfo != nil {
- embeddedCases, err := s.generateFieldEncoding(fieldTypeInfo.Fields())
- if err != nil {
- return nil, err
- }
- if field.IsPointer {
- result = append(result, fmt.Sprintf(" if %v != nil {", field.Accessor))
- for _, code := range embeddedCases {
- result = append(result, " "+code)
- }
- result = append(result, " }")
- } else {
- result = append(result, embeddedCases...)
- }
- }
- return result, nil
-}
-
-func (s *Struct) generateFieldEncoding(fields []*toolbox.FieldInfo) ([]string, error) {
- fieldCases := []string{}
- for i := range fields {
- if isSkipable(s.options, fields[i]) {
- continue
- }
- var templateKey = -1
- fieldTypeInfo := s.Type(normalizeTypeName(fields[i].TypeName))
- field, err := NewField(s, fields[i], fieldTypeInfo)
- if err != nil {
- return nil, err
- }
- if field.IsAnonymous {
- embedded, err := s.generateEmbeddedFieldEncoding(field, fieldTypeInfo)
- if err != nil {
- return nil, err
- }
- fieldCases = append(fieldCases, embedded...)
- continue
- }
- main:
- switch field.Type {
- case "string", "bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64":
- templateKey = encodeBaseType
- case "[]string", "[]bool", "[]int", "[]int8", "[]int16", "[]int32", "[]int64", "[]uint", "[]uint8", "[]uint16", "[]uint32", "[]uint64", "[]float32", "[]float64":
- templateKey = encodeBaseTypeSlice
- s.generatePrimitiveArray(field)
- case "[]byte":
- templateKey = encodeRawType
- default:
- if fieldTypeInfo != nil {
- if !(field.IsSlice || fieldTypeInfo.IsSlice) {
- templateKey = encodeStruct
- break main
- }
- switch fieldTypeInfo.ComponentType {
- case "byte":
- templateKey = encodeRawType
- break main
- case "string", "bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64":
- templateKey = decodeBaseTypeSlice
- break main
- }
- templateKey = encodeStructSlice
- break main
- } else if field.IsSlice {
- templateKey = encodeStructSlice
- } else if strings.HasSuffix(field.Type, "time.Time") {
- templateKey = encodeTime
- } else {
- templateKey = encodeUnknown
- }
- }
- if templateKey != -1 {
- decodingCase, err := expandFieldTemplate(templateKey, field)
- if err != nil {
- return nil, err
- }
- fieldCases = append(fieldCases, decodingCase)
- }
-
- }
- return fieldCases, nil
-}
-
-func NewStruct(info *toolbox.TypeInfo, generator *Generator) *Struct {
- return &Struct{
- TypeInfo: info,
- Generator: generator,
- Alias: extractReceiverAlias(info.Name),
- }
-}
diff --git a/codegen/template.go b/codegen/template.go
@@ -1,272 +0,0 @@
-package codegen
-
-import (
- "bytes"
- "fmt"
- "text/template"
-)
-
-const (
- decodeBaseType = iota
- encodeBaseType
- decodeBaseTypeSlice
- encodeBaseTypeSlice
- decodeRawType
- encodeRawType
- decodeStruct
- encodeStruct
-
- decodeStructSlice
- encodeStructSlice
- decodeTime
- encodeTime
-
- decodeUnknown
- encodeUnknown
-
- resetFieldValue
- poolInstanceRelease
- poolSliceInstanceRelease
-)
-
-var fieldTemplate = map[int]string{
- decodeBaseType: ` case "{{.Key}}":
-{{if .IsPointer}} var value {{.Type}}
- err := dec.{{.DecodingMethod}}(&value)
- if err == nil {
- {{.Accessor}} = &value
- }
- return err
-{{else}} return dec.{{.DecodingMethod}}(&{{.Accessor}}){{end}}
-`,
- encodeBaseType: ` enc.{{.EncodingMethod}}Key{{.OmitEmpty}}("{{.Key}}", {{.DereferenceModifier}}{{.Accessor}})`,
-
- decodeBaseTypeSlice: ` case "{{.Key}}":
- var aSlice = {{.HelperType}}{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- {{.Mutator}} = {{.RawType}}(aSlice)
- }
- return err
-`,
- encodeBaseTypeSlice: ` var {{.Var}}Slice = {{.HelperType}}({{.Accessor}})
- enc.ArrayKey{{.OmitEmpty}}("{{.Key}}",{{.Var}}Slice)`,
-
- decodeRawType: ` case "{{.Key}}":
- var value = gojay.EmbeddedJSON{}
- err := dec.AddEmbeddedJSON(&value)
- if err == nil && len(value) > 0 {
- {{.Mutator}} = {{.Type}}(value)
- }
- return err
-`,
-
- encodeRawType: ` var {{.Var}}Slice = gojay.EmbeddedJSON({{.Accessor}})
- enc.AddEmbeddedJSONKey{{.OmitEmpty}}("{{.Key}}", &{{.Var}}Slice)`,
- decodeStruct: ` case "{{.Key}}":{{if .IsPointer}}
- var value = {{.Init}}
- err := dec.Object(value)
- if err == nil {
- {{.Mutator}} = value
- }
-{{else}}
- err := dec.Object(&{{.Mutator}})
-{{end}}
- return err
-`,
- encodeStruct: ` enc.ObjectKey{{.OmitEmpty}}("{{.Key}}", {{.PointerModifier}}{{.Accessor}})`,
-
- decodeStructSlice: ` case "{{.Key}}":
- var aSlice = {{.HelperType}}{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- {{.Mutator}} = {{.RawType}}(aSlice)
- }
- return err
- `,
-
- encodeStructSlice: ` var {{.Var}}Slice = {{.HelperType}}({{.Accessor}})
- enc.ArrayKey{{.OmitEmpty}}("{{.Key}}", {{.DereferenceModifier}}{{.Var}}Slice)`,
-
- decodeTime: ` case "{{.Key}}":
- var format = {{.TimeLayout}}
- var value = {{.Init}}
- err := dec.DecodeTime({{.PointerModifier}}value, format){{if .IsPointer}}
- if err == nil {
- {{.Mutator}} = value
- }{{end}}
- return err
-`,
-
- encodeTime: `{{if .IsPointer}} if {{.Accessor}} != nil {
- enc.TimeKey("{{.Key}}", {{.PointerModifier}}{{.Accessor}}, {{.TimeLayout}})
- }{{else}} enc.TimeKey("{{.Key}}", {{.PointerModifier}}{{.Accessor}}, {{.TimeLayout}}){{end}}`,
- decodeUnknown: ` case "{{.Key}}":
- //TODO
- //dec.Any({{.Accessor}})
- return nil
-`,
- encodeUnknown: `
- //TODO
- //enc.Any({{.Accessor}})
-
-`,
- resetFieldValue: `{{if .ResetDependency}}{{.ResetDependency}}
-{{end}} {{.Mutator}} = {{.Reset}}`,
- poolInstanceRelease: ` {{.PoolName}}.Put({{.Accessor}})`,
-
- poolSliceInstanceRelease: ` for i := range {{.Accessor}} {
- {{.Accessor}}[i].Reset()
- {{.PoolName}}.Put({{.PointerModifier}}{{.Accessor}}[i])
- }`,
-}
-
-const (
- fileCode = iota
- encodingStructType
- baseTypeSlice
- structTypeSlice
- resetStruct
- poolVar
- poolInit
- embeddedStructInit
-)
-
-var blockTemplate = map[int]string{
- fileCode: `// Code generated by GoJayGen. DO NOT EDIT.\n\n
-package {{.Pkg}}
-
-import (
-{{.Imports}}
-)
-
-{{if .Init}}
-func init() {
-{{.Init}}
-}
-{{end}}
-
-{{.Code}}
-
-`,
- encodingStructType: `
-
-//MarshalJSONObject implements MarshalerJSONObject
-func ({{.Receiver}}) MarshalJSONObject(enc *gojay.Encoder) {
-{{.EncodingCases}}
-}
-
-//IsNil checks if instance is nil
-func ({{.Receiver}}) IsNil() bool {
- return {{.Alias}} == nil
-}
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func ({{.Receiver}}) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
-{{.InitEmbedded}}
- switch k {
-{{.DecodingCases}}
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func ({{.Receiver}}) NKeys() int { return {{.FieldCount}} }
-
-{{.Reset}}
-
-`,
-
- baseTypeSlice: `
-
-type {{.HelperType}} {{.RawType}}
-
-//UnmarshalJSONArray decodes JSON array elements into slice
-func (a *{{.HelperType}}) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value {{.ComponentType}}
- if err := dec.{{.DecodingMethod}}(&value); err != nil {
- return err
- }
- *a = append(*a, {{.ComponentInitModifier}}value)
- return nil
-}
-
-//MarshalJSONArray encodes arrays into JSON
-func (a {{.HelperType}}) MarshalJSONArray(enc *gojay.Encoder) {
- for _, item := range a {
- enc.{{.EncodingMethod}}({{.ComponentDereferenceModifier}}item)
- }
-}
-
-//IsNil checks if array is nil
-func (a {{.HelperType}}) IsNil() bool {
- return len(a) == 0
-}
-`,
-
- structTypeSlice: `
-type {{.HelperType}} {{.RawType}}
-
-func (s *{{.HelperType}}) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value = {{.ComponentInit}}
- if err := dec.Object({{.ComponentPointerModifier}}value); err != nil {
- return err
- }
- *s = append(*s, value)
- return nil
-}
-
-func (s {{.HelperType}}) MarshalJSONArray(enc *gojay.Encoder) {
- for i := range s {
- enc.Object({{.ComponentPointerModifier}}s[i])
- }
-}
-
-
-func (s {{.HelperType}}) IsNil() bool {
- return len(s) == 0
-}
-
-
-`,
-
- resetStruct: `
-// Reset reset fields
-func ({{.Receiver}}) Reset() {
-{{.Reset}}
-}
-`,
-
- poolVar: `var {{.PoolName}} *sync.Pool`,
- poolInit: ` {{.PoolName}} = &sync.Pool {
- New: func()interface{} {
- return &{{.Type}}{}
- },
- }`,
- embeddedStructInit: `if {{.Accessor}} == nil {
- {{.Accessor}} = {{.Init}}
- }`,
-}
-
-func expandTemplate(namespace string, dictionary map[int]string, key int, data interface{}) (string, error) {
- var id = fmt.Sprintf("%v_%v", namespace, key)
- textTemplate, ok := dictionary[key]
- if !ok {
- return "", fmt.Errorf("failed to lookup template for %v.%v", namespace, key)
- }
- temlate, err := template.New(id).Parse(textTemplate)
- if err != nil {
- return "", fmt.Errorf("fiailed to parse template %v %v, due to %v", namespace, key, err)
- }
- writer := new(bytes.Buffer)
- err = temlate.Execute(writer, data)
- return writer.String(), err
-}
-
-func expandFieldTemplate(key int, data interface{}) (string, error) {
- return expandTemplate("fieldTemplate", fieldTemplate, key, data)
-}
-
-func expandBlockTemplate(key int, data interface{}) (string, error) {
- return expandTemplate("blockTemplate", blockTemplate, key, data)
-}
diff --git a/codegen/test/annotated_struct/encoding.go b/codegen/test/annotated_struct/encoding.go
@@ -1,307 +0,0 @@
-// Code generated by GoJayGen. DO NOT EDIT.\n\n
-package annotated_struct
-
-import (
-"github.com/francoispqt/gojay"
-"time"
-)
-
-
-
-
-
-
-type Ints []int
-
-//UnmarshalJSONArray decodes JSON array elements into slice
-func (a *Ints) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value int
- if err := dec.Int(&value); err != nil {
- return err
- }
- *a = append(*a, value)
- return nil
-}
-
-//MarshalJSONArray encodes arrays into JSON
-func (a Ints) MarshalJSONArray(enc *gojay.Encoder) {
- for _, item := range a {
- enc.Int(item)
- }
-}
-
-//IsNil checks if array is nil
-func (a Ints) IsNil() bool {
- return len(a) == 0
-}
-
-
-
-type Float32sPtr []*float32
-
-//UnmarshalJSONArray decodes JSON array elements into slice
-func (a *Float32sPtr) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value float32
- if err := dec.Float32(&value); err != nil {
- return err
- }
- *a = append(*a, &value)
- return nil
-}
-
-//MarshalJSONArray encodes arrays into JSON
-func (a Float32sPtr) MarshalJSONArray(enc *gojay.Encoder) {
- for _, item := range a {
- enc.Float32(*item)
- }
-}
-
-//IsNil checks if array is nil
-func (a Float32sPtr) IsNil() bool {
- return len(a) == 0
-}
-
-
-type SubMessagesPtr []*SubMessage
-
-func (s *SubMessagesPtr) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value = &SubMessage{}
- if err := dec.Object(value); err != nil {
- return err
- }
- *s = append(*s, value)
- return nil
-}
-
-func (s SubMessagesPtr) MarshalJSONArray(enc *gojay.Encoder) {
- for i := range s {
- enc.Object(s[i])
- }
-}
-
-
-func (s SubMessagesPtr) IsNil() bool {
- return len(s) == 0
-}
-
-
-
-
-type SubMessages []SubMessage
-
-func (s *SubMessages) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value = SubMessage{}
- if err := dec.Object(&value); err != nil {
- return err
- }
- *s = append(*s, value)
- return nil
-}
-
-func (s SubMessages) MarshalJSONArray(enc *gojay.Encoder) {
- for i := range s {
- enc.Object(&s[i])
- }
-}
-
-
-func (s SubMessages) IsNil() bool {
- return len(s) == 0
-}
-
-
-
-
-
-
-//MarshalJSONObject implements MarshalerJSONObject
-func (m *SubMessage) MarshalJSONObject(enc *gojay.Encoder) {
- enc.IntKey("id", m.Id)
- enc.StringKey("description", m.Description)
- enc.TimeKey("startDate", &m.StartTime, "2006-01-02 15:04:05")
- if m.EndTime != nil {
- enc.TimeKey("endDate", m.EndTime, "2006-01-02 15:04:05")
- }
-}
-
-//IsNil checks if instance is nil
-func (m *SubMessage) IsNil() bool {
- return m == nil
-}
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (m *SubMessage) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
-
- switch k {
- case "id":
- return dec.Int(&m.Id)
-
- case "description":
- return dec.String(&m.Description)
-
- case "startDate":
- var format = "2006-01-02 15:04:05"
- var value = time.Time{}
- err := dec.DecodeTime(&value, format)
- return err
-
- case "endDate":
- var format = "2006-01-02 15:04:05"
- var value = &time.Time{}
- err := dec.DecodeTime(value, format)
- if err == nil {
- m.EndTime = value
- }
- return err
-
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (m *SubMessage) NKeys() int { return 4 }
-
-
-
-
-
-
-//MarshalJSONObject implements MarshalerJSONObject
-func (p *Paylod) MarshalJSONObject(enc *gojay.Encoder) {
-
-}
-
-//IsNil checks if instance is nil
-func (p *Paylod) IsNil() bool {
- return p == nil
-}
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (p *Paylod) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
-
- switch k {
-
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (p *Paylod) NKeys() int { return 0 }
-
-
-
-
-
-
-//MarshalJSONObject implements MarshalerJSONObject
-func (m *Message) MarshalJSONObject(enc *gojay.Encoder) {
- enc.IntKey("id", m.Id)
- enc.StringKey("name", m.Name)
- enc.Float64Key("price", m.Price)
- var intsSlice = Ints(m.Ints)
- enc.ArrayKey("ints",intsSlice)
- var floatsSlice = Float32sPtr(m.Floats)
- enc.ArrayKey("floats",floatsSlice)
- enc.ObjectKey("subMessageX", m.SubMessageX)
- var messagesXSlice = SubMessagesPtr(m.MessagesX)
- enc.ArrayKey("messagesX", messagesXSlice)
- enc.ObjectKey("SubMessageY", &m.SubMessageY)
- var messagesYSlice = SubMessages(m.MessagesY)
- enc.ArrayKey("MessagesY", messagesYSlice)
- enc.BoolKey("enabled", *m.IsTrue)
- var payloadSlice = gojay.EmbeddedJSON(m.Payload)
- enc.AddEmbeddedJSONKey("data", &payloadSlice)
-}
-
-//IsNil checks if instance is nil
-func (m *Message) IsNil() bool {
- return m == nil
-}
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (m *Message) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
-
- switch k {
- case "id":
- return dec.Int(&m.Id)
-
- case "name":
- return dec.String(&m.Name)
-
- case "price":
- return dec.Float64(&m.Price)
-
- case "ints":
- var aSlice = Ints{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.Ints = []int(aSlice)
- }
- return err
-
- case "floats":
- var aSlice = Float32sPtr{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.Floats = []*float32(aSlice)
- }
- return err
-
- case "subMessageX":
- var value = &SubMessage{}
- err := dec.Object(value)
- if err == nil {
- m.SubMessageX = value
- }
-
- return err
-
- case "messagesX":
- var aSlice = SubMessagesPtr{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.MessagesX = []*SubMessage(aSlice)
- }
- return err
-
- case "SubMessageY":
- err := dec.Object(&m.SubMessageY)
-
- return err
-
- case "MessagesY":
- var aSlice = SubMessages{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.MessagesY = []SubMessage(aSlice)
- }
- return err
-
- case "enabled":
- var value bool
- err := dec.Bool(&value)
- if err == nil {
- m.IsTrue = &value
- }
- return err
-
-
- case "data":
- var value = gojay.EmbeddedJSON{}
- err := dec.AddEmbeddedJSON(&value)
- if err == nil && len(value) > 0 {
- m.Payload = Paylod(value)
- }
- return err
-
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (m *Message) NKeys() int { return 11 }
-
-
-
-
-
diff --git a/codegen/test/annotated_struct/encoding_test.go b/codegen/test/annotated_struct/encoding_test.go
@@ -1,216 +0,0 @@
-package annotated_struct
-
-import (
- "testing"
- "github.com/stretchr/testify/assert"
- "github.com/francoispqt/gojay"
- "github.com/viant/assertly"
- "log"
- "bytes"
-)
-
-func TestMessage_Unmarshal(t *testing.T) {
-
-
-
- input := `{
- "id": 1022,
- "name": "name acc",
- "price": 13.3,
- "ints": [
- 1,
- 2,
- 5
- ],
- "floats": [
- 2.3,
- 4.6,
- 7.4
- ],
- "subMessageX": {
- "id": 102,
- "description": "abcd"
- },
- "messagesX": [
- {
- "id": 2102,
- "description": "abce"
- }
- ],
- "SubMessageY": {
- "id": 3102,
- "description": "abcf"
- },
- "MessagesY": [
- {
- "id": 5102,
- "description": "abcg"
- },
- {
- "id": 5106,
- "description": "abcgg"
- }
- ],
- "enabled": true,
- "data": "123"
-}`
-
-
- expacted := `{
- "Id": 1022,
- "Name": "name acc",
- "Price": 13.3,
- "Ints": [
- 1,
- 2,
- 5
- ],
- "Floats": [
- 2.3,
- 4.6,
- 7.4
- ],
- "SubMessageX": {
- "Id": 102,
- "Description": "abcd"
- },
- "MessagesX": [
- {
- "Id": 2102,
- "Description": "abce"
- }
- ],
- "SubMessageY": {
- "Id": 3102,
- "Description": "abcf"
- },
- "MessagesY": [
- {
- "Id": 5102,
- "Description": "abcg"
- },
- {
- "Id": 5106,
- "Description": "abcgg"
- }
- ],
- "IsTrue": true,
- "Payload": "\"123\""
-}`
-
- var err error
- var data = []byte(input)
- message := &Message{}
- err = gojay.UnmarshalJSONObject(data, message)
- if !assert.Nil(t, err) {
- log.Fatal(err)
- }
- assertly.AssertValues(t, expacted, message)
-}
-
-
-
-
-func TestMessage_Marshal(t *testing.T) {
-
- input := `{
- "id": 1022,
- "name": "name acc",
- "price": 13.3,
- "ints": [
- 1,
- 2,
- 5
- ],
- "floats": [
- 2.3,
- 4.6,
- 7.4
- ],
- "subMessageX": {
- "id": 102,
- "description": "abcd"
- },
- "messagesX": [
- {
- "id": 2102,
- "description": "abce"
- }
- ],
- "SubMessageY": {
- "id": 3102,
- "description": "abcf"
- },
- "MessagesY": [
- {
- "id": 5102,
- "description": "abcg"
- },
- {
- "id": 5106,
- "description": "abcgg"
- }
- ],
- "enabled": true,
- "data": "123"
-}`
-
-
- expacted := `{
- "Id": 1022,
- "Name": "name acc",
- "Price": 13.3,
- "Ints": [
- 1,
- 2,
- 5
- ],
- "Floats": [
- 2.3,
- 4.6,
- 7.4
- ],
- "SubMessageX": {
- "Id": 102,
- "Description": "abcd"
- },
- "MessagesX": [
- {
- "Id": 2102,
- "Description": "abce"
- }
- ],
- "SubMessageY": {
- "Id": 3102,
- "Description": "abcf"
- },
- "MessagesY": [
- {
- "Id": 5102,
- "Description": "abcg"
- },
- {
- "Id": 5106,
- "Description": "abcgg"
- }
- ],
- "IsTrue": true,
- "Payload": "\"123\""
-}`
-
- var err error
- var data = []byte(input)
- message := &Message{}
- err = gojay.UnmarshalJSONObject(data, message)
- if !assert.Nil(t, err) {
- log.Fatal(err)
- }
- assertly.AssertValues(t, expacted, message)
- var writer = new(bytes.Buffer)
- encoder := gojay.NewEncoder(writer)
- err = encoder.Encode(message)
- assert.Nil(t, err)
- var JSON = writer.String()
- assertly.AssertValues(t, input, JSON)
-
-}
-\ No newline at end of file
diff --git a/codegen/test/annotated_struct/message.go b/codegen/test/annotated_struct/message.go
@@ -1,19 +0,0 @@
-package annotated_struct
-
-
-type Paylod []byte
-
-type Message struct {
- Id int `json:"id"`
- Name string `json:"name"`
- Price float64 `json:"price"`
- Ints []int `json:"ints"`
- Floats []*float32 `json:"floats"`
- SubMessageX *SubMessage `json:"subMessageX"`
- MessagesX []*SubMessage `json:"messagesX"`
- SubMessageY SubMessage
- MessagesY []SubMessage
- IsTrue *bool `json:"enabled"`
- Payload Paylod `json:"data"`
- Ignore string `json:"-"`
-}
diff --git a/codegen/test/annotated_struct/sub_message.go b/codegen/test/annotated_struct/sub_message.go
@@ -1,10 +0,0 @@
-package annotated_struct
-
-import "time"
-
-type SubMessage struct {
- Id int `json:"id"`
- Description string `json:"description"`
- StartTime time.Time `json:"startDate" timeFormat:"yyyy-MM-dd HH:mm:ss"`
- EndTime *time.Time `json:"endDate" timeLayout:"2006-01-02 15:04:05"`
-}
diff --git a/codegen/test/basic_struct/encoding.go b/codegen/test/basic_struct/encoding.go
@@ -1,280 +0,0 @@
-// Code generated by GoJayGen. DO NOT EDIT.\n\n
-package basic_struct
-
-import (
-"github.com/francoispqt/gojay"
-"time"
-)
-
-
-
-
-
-
-type Ints []int
-
-//UnmarshalJSONArray decodes JSON array elements into slice
-func (a *Ints) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value int
- if err := dec.Int(&value); err != nil {
- return err
- }
- *a = append(*a, value)
- return nil
-}
-
-//MarshalJSONArray encodes arrays into JSON
-func (a Ints) MarshalJSONArray(enc *gojay.Encoder) {
- for _, item := range a {
- enc.Int(item)
- }
-}
-
-//IsNil checks if array is nil
-func (a Ints) IsNil() bool {
- return len(a) == 0
-}
-
-
-
-type Float32sPtr []*float32
-
-//UnmarshalJSONArray decodes JSON array elements into slice
-func (a *Float32sPtr) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value float32
- if err := dec.Float32(&value); err != nil {
- return err
- }
- *a = append(*a, &value)
- return nil
-}
-
-//MarshalJSONArray encodes arrays into JSON
-func (a Float32sPtr) MarshalJSONArray(enc *gojay.Encoder) {
- for _, item := range a {
- enc.Float32(*item)
- }
-}
-
-//IsNil checks if array is nil
-func (a Float32sPtr) IsNil() bool {
- return len(a) == 0
-}
-
-
-type SubMessagesPtr []*SubMessage
-
-func (s *SubMessagesPtr) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value = &SubMessage{}
- if err := dec.Object(value); err != nil {
- return err
- }
- *s = append(*s, value)
- return nil
-}
-
-func (s SubMessagesPtr) MarshalJSONArray(enc *gojay.Encoder) {
- for i := range s {
- enc.Object(s[i])
- }
-}
-
-
-func (s SubMessagesPtr) IsNil() bool {
- return len(s) == 0
-}
-
-
-
-
-type SubMessages []SubMessage
-
-func (s *SubMessages) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value = SubMessage{}
- if err := dec.Object(&value); err != nil {
- return err
- }
- *s = append(*s, value)
- return nil
-}
-
-func (s SubMessages) MarshalJSONArray(enc *gojay.Encoder) {
- for i := range s {
- enc.Object(&s[i])
- }
-}
-
-
-func (s SubMessages) IsNil() bool {
- return len(s) == 0
-}
-
-
-
-
-
-
-//MarshalJSONObject implements MarshalerJSONObject
-func (m *SubMessage) MarshalJSONObject(enc *gojay.Encoder) {
- enc.IntKey("Id", m.Id)
- enc.StringKey("Description", m.Description)
- enc.TimeKey("StartTime", &m.StartTime, time.RFC3339)
- if m.EndTime != nil {
- enc.TimeKey("EndTime", m.EndTime, time.RFC3339)
- }
-}
-
-//IsNil checks if instance is nil
-func (m *SubMessage) IsNil() bool {
- return m == nil
-}
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (m *SubMessage) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
-
- switch k {
- case "Id":
- return dec.Int(&m.Id)
-
- case "Description":
- return dec.String(&m.Description)
-
- case "StartTime":
- var format = time.RFC3339
- var value = time.Time{}
- err := dec.DecodeTime(&value, format)
- return err
-
- case "EndTime":
- var format = time.RFC3339
- var value = &time.Time{}
- err := dec.DecodeTime(value, format)
- if err == nil {
- m.EndTime = value
- }
- return err
-
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (m *SubMessage) NKeys() int { return 4 }
-
-
-
-
-
-
-//MarshalJSONObject implements MarshalerJSONObject
-func (m *Message) MarshalJSONObject(enc *gojay.Encoder) {
- enc.IntKey("Id", m.Id)
- enc.StringKey("Name", m.Name)
- enc.Float64Key("Price", m.Price)
- var intsSlice = Ints(m.Ints)
- enc.ArrayKey("Ints",intsSlice)
- var floatsSlice = Float32sPtr(m.Floats)
- enc.ArrayKey("Floats",floatsSlice)
- enc.ObjectKey("SubMessageX", m.SubMessageX)
- var messagesXSlice = SubMessagesPtr(m.MessagesX)
- enc.ArrayKey("MessagesX", messagesXSlice)
- enc.ObjectKey("SubMessageY", &m.SubMessageY)
- var messagesYSlice = SubMessages(m.MessagesY)
- enc.ArrayKey("MessagesY", messagesYSlice)
- enc.BoolKey("IsTrue", *m.IsTrue)
- var payloadSlice = gojay.EmbeddedJSON(m.Payload)
- enc.AddEmbeddedJSONKey("Payload", &payloadSlice)
-}
-
-//IsNil checks if instance is nil
-func (m *Message) IsNil() bool {
- return m == nil
-}
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (m *Message) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
-
- switch k {
- case "Id":
- return dec.Int(&m.Id)
-
- case "Name":
- return dec.String(&m.Name)
-
- case "Price":
- return dec.Float64(&m.Price)
-
- case "Ints":
- var aSlice = Ints{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.Ints = []int(aSlice)
- }
- return err
-
- case "Floats":
- var aSlice = Float32sPtr{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.Floats = []*float32(aSlice)
- }
- return err
-
- case "SubMessageX":
- var value = &SubMessage{}
- err := dec.Object(value)
- if err == nil {
- m.SubMessageX = value
- }
-
- return err
-
- case "MessagesX":
- var aSlice = SubMessagesPtr{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.MessagesX = []*SubMessage(aSlice)
- }
- return err
-
- case "SubMessageY":
- err := dec.Object(&m.SubMessageY)
-
- return err
-
- case "MessagesY":
- var aSlice = SubMessages{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.MessagesY = []SubMessage(aSlice)
- }
- return err
-
- case "IsTrue":
- var value bool
- err := dec.Bool(&value)
- if err == nil {
- m.IsTrue = &value
- }
- return err
-
-
- case "Payload":
- var value = gojay.EmbeddedJSON{}
- err := dec.AddEmbeddedJSON(&value)
- if err == nil && len(value) > 0 {
- m.Payload = []byte(value)
- }
- return err
-
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (m *Message) NKeys() int { return 11 }
-
-
-
-
-
diff --git a/codegen/test/basic_struct/encoding_test.go b/codegen/test/basic_struct/encoding_test.go
@@ -1,122 +0,0 @@
-package basic_struct
-
-import (
- "testing"
- "github.com/stretchr/testify/assert"
- "github.com/francoispqt/gojay"
- "github.com/viant/assertly"
- "bytes"
-)
-
-func TestMessage_Unmarshal(t *testing.T) {
-
- input := `{
- "Id": 1022,
- "Name": "name acc",
- "Price": 13.3,
- "Ints": [
- 1,
- 2,
- 5
- ],
- "Floats": [
- 2.3,
- 4.6,
- 7.4
- ],
- "SubMessageX": {
- "Id": 102,
- "Description": "abcd"
- },
- "MessagesX": [
- {
- "Id": 2102,
- "Description": "abce"
- }
- ],
- "SubMessageY": {
- "Id": 3102,
- "Description": "abcf"
- },
- "MessagesY": [
- {
- "Id": 5102,
- "Description": "abcg"
- },
- {
- "Id": 5106,
- "Description": "abcgg"
- }
- ],
- "IsTrue": true,
- "Payload": ""
-}`
-
- var err error
- var data = []byte(input)
- message := &Message{}
- err = gojay.UnmarshalJSONObject(data, message)
- assert.Nil(t, err)
- assertly.AssertValues(t, input, message)
-}
-
-
-
-func TestMessage_Marshal(t *testing.T) {
-
- input := `{
- "Id": 1022,
- "Name": "name acc",
- "Price": 13.3,
- "Ints": [
- 1,
- 2,
- 5
- ],
- "Floats": [
- 2.3,
- 4.6,
- 7.4
- ],
- "SubMessageX": {
- "Id": 102,
- "Description": "abcd"
- },
- "MessagesX": [
- {
- "Id": 2102,
- "Description": "abce"
- }
- ],
- "SubMessageY": {
- "Id": 3102,
- "Description": "abcf"
- },
- "MessagesY": [
- {
- "Id": 5102,
- "Description": "abcg"
- },
- {
- "Id": 5106,
- "Description": "abcgg"
- }
- ],
- "IsTrue": true,
- "Payload": ""
-}`
-
- var err error
- var data = []byte(input)
- message := &Message{}
- err = gojay.UnmarshalJSONObject(data, message)
- assert.Nil(t, err)
-
- var writer = new(bytes.Buffer)
-
- encoder := gojay.NewEncoder(writer)
- err = encoder.Encode(message)
- assert.Nil(t, err)
- var JSON = writer.String()
- assertly.AssertValues(t, input, JSON)
-}
diff --git a/codegen/test/basic_struct/message.go b/codegen/test/basic_struct/message.go
@@ -1,18 +0,0 @@
-package basic_struct
-
-
-
-
-type Message struct {
- Id int
- Name string
- Price float64
- Ints []int
- Floats []*float32
- SubMessageX *SubMessage
- MessagesX []*SubMessage
- SubMessageY SubMessage
- MessagesY []SubMessage
- IsTrue *bool
- Payload []byte
-}
diff --git a/codegen/test/basic_struct/sub_message.go b/codegen/test/basic_struct/sub_message.go
@@ -1,10 +0,0 @@
-package basic_struct
-
-import "time"
-
-type SubMessage struct {
- Id int
- Description string
- StartTime time.Time
- EndTime *time.Time
-}
diff --git a/codegen/test/embedded_struct/encoding.go b/codegen/test/embedded_struct/encoding.go
@@ -1,336 +0,0 @@
-// Code generated by GoJayGen. DO NOT EDIT.\n\n
-package embedded_struct
-
-import (
-"github.com/francoispqt/gojay"
-"time"
-)
-
-
-
-
-
-type SubMessagesPtr []*SubMessage
-
-func (s *SubMessagesPtr) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value = &SubMessage{}
- if err := dec.Object(value); err != nil {
- return err
- }
- *s = append(*s, value)
- return nil
-}
-
-func (s SubMessagesPtr) MarshalJSONArray(enc *gojay.Encoder) {
- for i := range s {
- enc.Object(s[i])
- }
-}
-
-
-func (s SubMessagesPtr) IsNil() bool {
- return len(s) == 0
-}
-
-
-
-
-type SubMessages []SubMessage
-
-func (s *SubMessages) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value = SubMessage{}
- if err := dec.Object(&value); err != nil {
- return err
- }
- *s = append(*s, value)
- return nil
-}
-
-func (s SubMessages) MarshalJSONArray(enc *gojay.Encoder) {
- for i := range s {
- enc.Object(&s[i])
- }
-}
-
-
-func (s SubMessages) IsNil() bool {
- return len(s) == 0
-}
-
-
-
-
-
-type Ints []int
-
-//UnmarshalJSONArray decodes JSON array elements into slice
-func (a *Ints) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value int
- if err := dec.Int(&value); err != nil {
- return err
- }
- *a = append(*a, value)
- return nil
-}
-
-//MarshalJSONArray encodes arrays into JSON
-func (a Ints) MarshalJSONArray(enc *gojay.Encoder) {
- for _, item := range a {
- enc.Int(item)
- }
-}
-
-//IsNil checks if array is nil
-func (a Ints) IsNil() bool {
- return len(a) == 0
-}
-
-
-
-type Float32sPtr []*float32
-
-//UnmarshalJSONArray decodes JSON array elements into slice
-func (a *Float32sPtr) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value float32
- if err := dec.Float32(&value); err != nil {
- return err
- }
- *a = append(*a, &value)
- return nil
-}
-
-//MarshalJSONArray encodes arrays into JSON
-func (a Float32sPtr) MarshalJSONArray(enc *gojay.Encoder) {
- for _, item := range a {
- enc.Float32(*item)
- }
-}
-
-//IsNil checks if array is nil
-func (a Float32sPtr) IsNil() bool {
- return len(a) == 0
-}
-
-
-
-
-//MarshalJSONObject implements MarshalerJSONObject
-func (i *BaseId) MarshalJSONObject(enc *gojay.Encoder) {
- enc.IntKey("Id", i.Id)
- enc.StringKey("Name", i.Name)
-}
-
-//IsNil checks if instance is nil
-func (i *BaseId) IsNil() bool {
- return i == nil
-}
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (i *BaseId) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
-
- switch k {
- case "Id":
- return dec.Int(&i.Id)
-
- case "Name":
- return dec.String(&i.Name)
-
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (i *BaseId) NKeys() int { return 2 }
-
-
-
-
-
-
-//MarshalJSONObject implements MarshalerJSONObject
-func (m *SubMessage) MarshalJSONObject(enc *gojay.Encoder) {
- enc.StringKey("Description", m.Description)
- enc.TimeKey("StartTime", &m.StartTime, time.RFC3339)
- if m.EndTime != nil {
- enc.TimeKey("EndTime", m.EndTime, time.RFC3339)
- }
-}
-
-//IsNil checks if instance is nil
-func (m *SubMessage) IsNil() bool {
- return m == nil
-}
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (m *SubMessage) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
-
- switch k {
- case "Description":
- return dec.String(&m.Description)
-
- case "StartTime":
- var format = time.RFC3339
- var value = time.Time{}
- err := dec.DecodeTime(&value, format)
- return err
-
- case "EndTime":
- var format = time.RFC3339
- var value = &time.Time{}
- err := dec.DecodeTime(value, format)
- if err == nil {
- m.EndTime = value
- }
- return err
-
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (m *SubMessage) NKeys() int { return 3 }
-
-
-
-
-
-
-//MarshalJSONObject implements MarshalerJSONObject
-func (m *Message) MarshalJSONObject(enc *gojay.Encoder) {
- if m.BaseId != nil {
- enc.IntKey("Id", m.Id)
- enc.StringKey("Name", m.Name)
- }
- enc.StringKey("Description", m.Description)
- enc.TimeKey("StartTime", &m.StartTime, time.RFC3339)
- if m.EndTime != nil {
- enc.TimeKey("EndTime", m.EndTime, time.RFC3339)
- }
- enc.Float64Key("Price", m.Price)
- var intsSlice = Ints(m.Ints)
- enc.ArrayKey("Ints",intsSlice)
- var floatsSlice = Float32sPtr(m.Floats)
- enc.ArrayKey("Floats",floatsSlice)
- enc.ObjectKey("SubMessageX", m.SubMessageX)
- var messagesXSlice = SubMessagesPtr(m.MessagesX)
- enc.ArrayKey("MessagesX", messagesXSlice)
- enc.ObjectKey("SubMessageY", &m.SubMessageY)
- var messagesYSlice = SubMessages(m.MessagesY)
- enc.ArrayKey("MessagesY", messagesYSlice)
- enc.BoolKey("IsTrue", *m.IsTrue)
- var payloadSlice = gojay.EmbeddedJSON(m.Payload)
- enc.AddEmbeddedJSONKey("Payload", &payloadSlice)
-}
-
-//IsNil checks if instance is nil
-func (m *Message) IsNil() bool {
- return m == nil
-}
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (m *Message) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
-if m.BaseId == nil {
- m.BaseId = &BaseId{}
- }
- switch k {
- case "Id":
- return dec.Int(&m.Id)
-
- case "Name":
- return dec.String(&m.Name)
-
- case "Description":
- return dec.String(&m.Description)
-
- case "StartTime":
- var format = time.RFC3339
- var value = time.Time{}
- err := dec.DecodeTime(&value, format)
- return err
-
- case "EndTime":
- var format = time.RFC3339
- var value = &time.Time{}
- err := dec.DecodeTime(value, format)
- if err == nil {
- m.EndTime = value
- }
- return err
-
- case "Price":
- return dec.Float64(&m.Price)
-
- case "Ints":
- var aSlice = Ints{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.Ints = []int(aSlice)
- }
- return err
-
- case "Floats":
- var aSlice = Float32sPtr{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.Floats = []*float32(aSlice)
- }
- return err
-
- case "SubMessageX":
- var value = &SubMessage{}
- err := dec.Object(value)
- if err == nil {
- m.SubMessageX = value
- }
-
- return err
-
- case "MessagesX":
- var aSlice = SubMessagesPtr{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.MessagesX = []*SubMessage(aSlice)
- }
- return err
-
- case "SubMessageY":
- err := dec.Object(&m.SubMessageY)
-
- return err
-
- case "MessagesY":
- var aSlice = SubMessages{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.MessagesY = []SubMessage(aSlice)
- }
- return err
-
- case "IsTrue":
- var value bool
- err := dec.Bool(&value)
- if err == nil {
- m.IsTrue = &value
- }
- return err
-
-
- case "Payload":
- var value = gojay.EmbeddedJSON{}
- err := dec.AddEmbeddedJSON(&value)
- if err == nil && len(value) > 0 {
- m.Payload = []byte(value)
- }
- return err
-
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (m *Message) NKeys() int { return 14 }
-
-
-
-
-
diff --git a/codegen/test/embedded_struct/encoding_test.go b/codegen/test/embedded_struct/encoding_test.go
@@ -1,108 +0,0 @@
-package embedded_struct
-
-import (
- "testing"
- "github.com/stretchr/testify/assert"
- "github.com/francoispqt/gojay"
- "github.com/viant/assertly"
- "bytes"
-)
-
-func TestMessage_Unmarshal(t *testing.T) {
-
- input := `{
- "Id": 1022,
- "Name": "name acc",
- "Description": "abcd",
- "Price": 13.3,
- "Ints": [
- 1,
- 2,
- 5
- ],
- "Floats": [
- 2.3,
- 4.6,
- 7.4
- ],
- "MessagesX": [
- {
- "Description": "abce"
- }
- ],
- "SubMessageY": {
- "Description": "abcf"
- },
- "MessagesY": [
- {
- "Description": "abcg"
- },
- {
- "Description": "abcgg"
- }
- ],
- "IsTrue": true,
- "Payload": ""
-}`
-
- var err error
- var data = []byte(input)
- message := &Message{}
- err = gojay.UnmarshalJSONObject(data, message)
- assert.Nil(t, err)
- assertly.AssertValues(t, input, message)
-}
-
-
-
-func TestMessage_Marshal(t *testing.T) {
-
- input := `{
- "Id": 1022,
- "Name": "name acc",
- "Description": "abcd",
- "Price": 13.3,
- "Ints": [
- 1,
- 2,
- 5
- ],
- "Floats": [
- 2.3,
- 4.6,
- 7.4
- ],
- "MessagesX": [
- {
- "Description": "abce"
- }
- ],
- "SubMessageY": {
- "Description": "abcf"
- },
- "MessagesY": [
- {
- "Description": "abcg"
- },
- {
- "Description": "abcgg"
- }
- ],
- "IsTrue": true,
- "Payload": ""
-}`
-
- var err error
- var data = []byte(input)
- message := &Message{}
- err = gojay.UnmarshalJSONObject(data, message)
- assert.Nil(t, err)
- assertly.AssertValues(t, input, message)
- var writer = new(bytes.Buffer)
-
- encoder := gojay.NewEncoder(writer)
- err = encoder.Encode(message)
- assert.Nil(t, err)
- var JSON = writer.String()
- assertly.AssertValues(t, input, JSON)
-}
-\ No newline at end of file
diff --git a/codegen/test/embedded_struct/message.go b/codegen/test/embedded_struct/message.go
@@ -1,22 +0,0 @@
-package embedded_struct
-
-
-type BaseId struct {
- Id int
- Name string
-
-}
-
-type Message struct {
- *BaseId
- SubMessage
- Price float64
- Ints []int
- Floats []*float32
- SubMessageX *SubMessage
- MessagesX []*SubMessage
- SubMessageY SubMessage
- MessagesY []SubMessage
- IsTrue *bool
- Payload []byte
-}
diff --git a/codegen/test/embedded_struct/sub_message.go b/codegen/test/embedded_struct/sub_message.go
@@ -1,9 +0,0 @@
-package embedded_struct
-
-import "time"
-
-type SubMessage struct {
- Description string
- StartTime time.Time
- EndTime *time.Time
-}
diff --git a/codegen/test/pooled_struct/encoding.go b/codegen/test/pooled_struct/encoding.go
@@ -1,326 +0,0 @@
-// Code generated by GoJayGen. DO NOT EDIT.\n\n
-package pooled_struct
-
-import (
-"sync"
-"time"
-"github.com/francoispqt/gojay"
-)
-
-
-func init() {
- MessagePool = &sync.Pool {
- New: func()interface{} {
- return &Message{}
- },
- }
- SubMessagePool = &sync.Pool {
- New: func()interface{} {
- return &SubMessage{}
- },
- }
-}
-
-
-var MessagePool *sync.Pool
-var SubMessagePool *sync.Pool
-
-
-
-type Ints []int
-
-//UnmarshalJSONArray decodes JSON array elements into slice
-func (a *Ints) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value int
- if err := dec.Int(&value); err != nil {
- return err
- }
- *a = append(*a, value)
- return nil
-}
-
-//MarshalJSONArray encodes arrays into JSON
-func (a Ints) MarshalJSONArray(enc *gojay.Encoder) {
- for _, item := range a {
- enc.Int(item)
- }
-}
-
-//IsNil checks if array is nil
-func (a Ints) IsNil() bool {
- return len(a) == 0
-}
-
-
-
-type Float32sPtr []*float32
-
-//UnmarshalJSONArray decodes JSON array elements into slice
-func (a *Float32sPtr) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value float32
- if err := dec.Float32(&value); err != nil {
- return err
- }
- *a = append(*a, &value)
- return nil
-}
-
-//MarshalJSONArray encodes arrays into JSON
-func (a Float32sPtr) MarshalJSONArray(enc *gojay.Encoder) {
- for _, item := range a {
- enc.Float32(*item)
- }
-}
-
-//IsNil checks if array is nil
-func (a Float32sPtr) IsNil() bool {
- return len(a) == 0
-}
-
-
-type SubMessagesPtr []*SubMessage
-
-func (s *SubMessagesPtr) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value = &SubMessage{}
- if err := dec.Object(value); err != nil {
- return err
- }
- *s = append(*s, value)
- return nil
-}
-
-func (s SubMessagesPtr) MarshalJSONArray(enc *gojay.Encoder) {
- for i := range s {
- enc.Object(s[i])
- }
-}
-
-
-func (s SubMessagesPtr) IsNil() bool {
- return len(s) == 0
-}
-
-
-
-
-type SubMessages []SubMessage
-
-func (s *SubMessages) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var value = SubMessage{}
- if err := dec.Object(&value); err != nil {
- return err
- }
- *s = append(*s, value)
- return nil
-}
-
-func (s SubMessages) MarshalJSONArray(enc *gojay.Encoder) {
- for i := range s {
- enc.Object(&s[i])
- }
-}
-
-
-func (s SubMessages) IsNil() bool {
- return len(s) == 0
-}
-
-
-
-
-
-
-//MarshalJSONObject implements MarshalerJSONObject
-func (m *SubMessage) MarshalJSONObject(enc *gojay.Encoder) {
- enc.IntKey("Id", m.Id)
- enc.StringKey("Description", m.Description)
- enc.TimeKey("StartTime", &m.StartTime, time.RFC3339)
- if m.EndTime != nil {
- enc.TimeKey("EndTime", m.EndTime, time.RFC3339)
- }
-}
-
-//IsNil checks if instance is nil
-func (m *SubMessage) IsNil() bool {
- return m == nil
-}
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (m *SubMessage) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
-
- switch k {
- case "Id":
- return dec.Int(&m.Id)
-
- case "Description":
- return dec.String(&m.Description)
-
- case "StartTime":
- var format = time.RFC3339
- var value = time.Time{}
- err := dec.DecodeTime(&value, format)
- return err
-
- case "EndTime":
- var format = time.RFC3339
- var value = &time.Time{}
- err := dec.DecodeTime(value, format)
- if err == nil {
- m.EndTime = value
- }
- return err
-
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (m *SubMessage) NKeys() int { return 4 }
-
-
-// Reset reset fields
-func (m *SubMessage) Reset() {
- m.Id = 0
- m.Description = ""
- m.EndTime = nil
-}
-
-
-
-
-
-//MarshalJSONObject implements MarshalerJSONObject
-func (m *Message) MarshalJSONObject(enc *gojay.Encoder) {
- enc.IntKey("Id", m.Id)
- enc.StringKey("Name", m.Name)
- enc.Float64Key("Price", m.Price)
- var intsSlice = Ints(m.Ints)
- enc.ArrayKey("Ints",intsSlice)
- var floatsSlice = Float32sPtr(m.Floats)
- enc.ArrayKey("Floats",floatsSlice)
- enc.ObjectKey("SubMessageX", m.SubMessageX)
- var messagesXSlice = SubMessagesPtr(m.MessagesX)
- enc.ArrayKey("MessagesX", messagesXSlice)
- enc.ObjectKey("SubMessageY", &m.SubMessageY)
- var messagesYSlice = SubMessages(m.MessagesY)
- enc.ArrayKey("MessagesY", messagesYSlice)
- enc.BoolKey("IsTrue", *m.IsTrue)
- var payloadSlice = gojay.EmbeddedJSON(m.Payload)
- enc.AddEmbeddedJSONKey("Payload", &payloadSlice)
-}
-
-//IsNil checks if instance is nil
-func (m *Message) IsNil() bool {
- return m == nil
-}
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (m *Message) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
-
- switch k {
- case "Id":
- return dec.Int(&m.Id)
-
- case "Name":
- return dec.String(&m.Name)
-
- case "Price":
- return dec.Float64(&m.Price)
-
- case "Ints":
- var aSlice = Ints{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.Ints = []int(aSlice)
- }
- return err
-
- case "Floats":
- var aSlice = Float32sPtr{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.Floats = []*float32(aSlice)
- }
- return err
-
- case "SubMessageX":
- var value = SubMessagePool.Get().(*SubMessage)
- err := dec.Object(value)
- if err == nil {
- m.SubMessageX = value
- }
-
- return err
-
- case "MessagesX":
- var aSlice = SubMessagesPtr{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.MessagesX = []*SubMessage(aSlice)
- }
- return err
-
- case "SubMessageY":
- err := dec.Object(&m.SubMessageY)
-
- return err
-
- case "MessagesY":
- var aSlice = SubMessages{}
- err := dec.Array(&aSlice)
- if err == nil && len(aSlice) > 0 {
- m.MessagesY = []SubMessage(aSlice)
- }
- return err
-
- case "IsTrue":
- var value bool
- err := dec.Bool(&value)
- if err == nil {
- m.IsTrue = &value
- }
- return err
-
-
- case "Payload":
- var value = gojay.EmbeddedJSON{}
- err := dec.AddEmbeddedJSON(&value)
- if err == nil && len(value) > 0 {
- m.Payload = []byte(value)
- }
- return err
-
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (m *Message) NKeys() int { return 11 }
-
-
-// Reset reset fields
-func (m *Message) Reset() {
- m.Id = 0
- m.Name = ""
- m.Price = 0.0
- m.Ints = nil
- m.Floats = nil
- SubMessagePool.Put(m.SubMessageX)
- m.SubMessageX = nil
- for i := range m.MessagesX {
- m.MessagesX[i].Reset()
- SubMessagePool.Put(m.MessagesX[i])
- }
- m.MessagesX = nil
- for i := range m.MessagesY {
- m.MessagesY[i].Reset()
- SubMessagePool.Put(&m.MessagesY[i])
- }
- m.MessagesY = nil
- m.IsTrue = nil
- m.Payload = nil
-}
-
-
-
-
diff --git a/codegen/test/pooled_struct/encoding_test.go b/codegen/test/pooled_struct/encoding_test.go
@@ -1,124 +0,0 @@
-package pooled_struct
-
-import (
- "testing"
- "github.com/francoispqt/gojay"
- "github.com/stretchr/testify/assert"
- "github.com/viant/assertly"
- "bytes"
-)
-
-func TestMessage_Unmarshal(t *testing.T) {
-
- input := `{
- "Id": 1022,
- "Name": "name acc",
- "Price": 13.3,
- "Ints": [
- 1,
- 2,
- 5
- ],
- "Floats": [
- 2.3,
- 4.6,
- 7.4
- ],
- "SubMessageX": {
- "Id": 102,
- "Description": "abcd"
- },
- "MessagesX": [
- {
- "Id": 2102,
- "Description": "abce"
- }
- ],
- "SubMessageY": {
- "Id": 3102,
- "Description": "abcf"
- },
- "MessagesY": [
- {
- "Id": 5102,
- "Description": "abcg"
- },
- {
- "Id": 5106,
- "Description": "abcgg"
- }
- ],
- "IsTrue": true,
- "Payload": ""
-}`
-
- var data = []byte(input)
- message := MessagePool.Get().(*Message)
- err :=gojay.UnmarshalJSONObject(data, message)
- assert.Nil(t, err)
- message.Reset()
- MessagePool.Put(message)
-
-}
-
-
-func TestMessage_Marshal(t *testing.T) {
-
- input := `{
- "Id": 1022,
- "Name": "name acc",
- "Price": 13.3,
- "Ints": [
- 1,
- 2,
- 5
- ],
- "Floats": [
- 2.3,
- 4.6,
- 7.4
- ],
- "SubMessageX": {
- "Id": 102,
- "Description": "abcd"
- },
- "MessagesX": [
- {
- "Id": 2102,
- "Description": "abce"
- }
- ],
- "SubMessageY": {
- "Id": 3102,
- "Description": "abcf"
- },
- "MessagesY": [
- {
- "Id": 5102,
- "Description": "abcg"
- },
- {
- "Id": 5106,
- "Description": "abcgg"
- }
- ],
- "IsTrue": true,
- "Payload": ""
-}`
-
- var data = []byte(input)
- message := MessagePool.Get().(*Message)
- err :=gojay.UnmarshalJSONObject(data, message)
- assert.Nil(t, err)
- defer func() {
- message.Reset()
- MessagePool.Put(message)
-
- }()
- var writer = new(bytes.Buffer)
- encoder := gojay.NewEncoder(writer)
- err = encoder.Encode(message)
- assert.Nil(t, err)
- var JSON = writer.String()
- assertly.AssertValues(t, input, JSON)
-}
-\ No newline at end of file
diff --git a/codegen/test/pooled_struct/message.go b/codegen/test/pooled_struct/message.go
@@ -1,18 +0,0 @@
-package pooled_struct
-
-
-
-
-type Message struct {
- Id int
- Name string
- Price float64
- Ints []int
- Floats []*float32
- SubMessageX *SubMessage
- MessagesX []*SubMessage
- SubMessageY SubMessage
- MessagesY []SubMessage
- IsTrue *bool
- Payload []byte
-}
diff --git a/codegen/test/pooled_struct/sub_message.go b/codegen/test/pooled_struct/sub_message.go
@@ -1,10 +0,0 @@
-package pooled_struct
-
-import "time"
-
-type SubMessage struct {
- Id int
- Description string
- StartTime time.Time
- EndTime *time.Time
-}
diff --git a/gojay/Gopkg.lock b/gojay/Gopkg.lock
@@ -1,14 +0,0 @@
-# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
-
-[[projects]]
- name = "github.com/fatih/structtag"
- packages = ["."]
- revision = "da3d9ab5b78fdc25d3a7614853b085200bd10da9"
- version = "v0.1.0"
-
-[solve-meta]
- analyzer-name = "dep"
- analyzer-version = 1
- inputs-digest = "859116499e74f6c88afba2065cef9e2ee1caa81d532e01ed144541f9d36faae8"
- solver-name = "gps-cdcl"
- solver-version = 1
diff --git a/gojay/Gopkg.toml b/gojay/Gopkg.toml
@@ -1,26 +0,0 @@
-
-# Gopkg.toml example
-#
-# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
-# for detailed Gopkg.toml documentation.
-#
-# required = ["github.com/user/thing/cmd/thing"]
-# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
-#
-# [[constraint]]
-# name = "github.com/user/project"
-# version = "1.0.0"
-#
-# [[constraint]]
-# name = "github.com/user/project2"
-# branch = "dev"
-# source = "github.com/myfork/project2"
-#
-# [[override]]
-# name = "github.com/x/y"
-# version = "2.4.0"
-
-
-[[constraint]]
- name = "github.com/fatih/structtag"
- version = "0.1.0"
diff --git a/gojay/Makefile b/gojay/Makefile
@@ -1,15 +0,0 @@
-.PHONY: build
-build:
- go build ./
-
-.PHONY: test
-test:
- go test -race -v .
-
-.PHONY: cover
-cover:
- 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/README.md b/gojay/README.md
@@ -1,63 +1,61 @@
# Gojay code generator
+This package provides a command line tool to generate gojay's marshaling and unmarshing interface implementation for custom struct type(s)
-This package provides a command line tool to generate gojay's marshaling and unmarshing interface implementation for struct, slice and map types.
## Get started
```sh
-go install github.com/francoispqt/gojay/gojay
+go install github.com/francoispqt/gojay/gojaygen
```
## Generate code
### Basic command
-
The basic command is straightforward and easy to use:
```sh
-gojay github.com/some/package TypeA,TypeB,TypeC output.go
+cd $GOPATH/src/github.com/user/project
+gojaygen -s . -p true -t MyType -o output.go
```
-If you just want to the output to stdout, omit the third parameter.
+If you just want to the output to stdout, omit the -o flag.
### Using flags
-
-- p package to parse, relative path to $GOPATH/src
-- s file/dir to path, can be a relative or absolute path
-- t types to generate (comma separated)
-- o output file (relative or absolute path)
+- s Source file/dir path, can be a relative or absolute path
+- t Types to generate with all its dependencies (comma separated)
+- a Annotation tag used to read metadata (default: json)
+- o Output file (relative or absolute path)
+- p Pool to reuse object (using sync.Pool)
Examples:
-- Specific types in a go package, to stdout:
-```sh
-gojay -p github.com/francoispqt/gojay/gojay/tests -t A,B,StrSlice
-```
-- Specific types in a go package, write to a file:
+- Generate `SomeType` type in `/tmp/myproj` go package, write to file `output.go`:
```sh
-gojay -p github.com/francoispqt/gojay/gojay/tests -t A,B,StrSlice -o output.go
+gojay -s /tmp/myproj -t SomeType -o output.go
```
-- Specific types in a go file, to stdout:
+- Generate type `SomeType` in file `somegofile.go`, with custom tag `gojay`, write to stdout:
```sh
-gojay -s somegofile.go -t SomeType
+gojay -s somegofile.go -a gojay -t SomeType
```
-## Gojay tags
-
+## Generator tags
You can add tags to your structs to control:
+
- the JSON key
-- skip a struct field only for unmarshaling
-- skip a struct field only for marshaling
- skip a struct field
-- the use of omit empty methods for marshaling
+- the use of omitempty methods for marshaling
+- timeFormat (java style data format)
+- timeLayout (golang time layout)
+
### Example:
```go
type A struct {
- Str string `gojay:"string"`
- StrOmitEmpty string `gojay:"string,omitempty"`
- SkipUnmarshal string `gojay:"skipUnmarshal,-u"`
- SkipMarshal string `gojay:"skipMarshal,-m"`
- Skip string `gojay:"-"`
+ Str string `json:"string"`
+ StrOmitEmpty string `json:"stringOrEmpty,omitempty"`
+ Skip string `json:"-"`
+ StartTime time.Time `json:"startDate" timeFormat:"yyyy-MM-dd HH:mm:ss"`
+ EndTime *time.Time `json:"endDate" timeLayout:"2006-01-02 15:04:05"`
}
```
+
diff --git a/gojay/codegen/field.go b/gojay/codegen/field.go
@@ -0,0 +1,168 @@
+package codegen
+
+import (
+ "fmt"
+ "github.com/viant/toolbox"
+ "strings"
+)
+
+//Field represents a field.
+type Field struct {
+ Key string
+ Init string
+ OmitEmpty string
+ TimeLayout string
+ NullType string
+ Name string
+ Accessor string
+ Mutator string
+ Receiver string //alias and type name
+ Alias string //object alias name
+ Var string //variable for this field
+ Type string
+ RawType string
+ HelperType string
+ ComponentType string
+ RawComponentType string
+ IsPointerComponent bool
+
+ PointerModifier string //takes field pointer, "&" if field is not a pointer type
+ DereferenceModifier string //take pointer value, i.e "*" if field has a pointer type
+
+ ComponentPointerModifier string //takes item pointer if needed,i.e
+ ComponentDereferenceModifier string //de reference value if needed, i.e
+ ComponentInitModifier string //takes item pointer if type is not a pointer type
+ ComponentInit string //initialises component type
+
+ DecodingMethod string
+ EncodingMethod string
+ PoolName string //pool name associated with this field
+ ResetDependency string
+ Reset string
+ IsAnonymous bool
+ IsPointer bool
+ IsSlice bool
+
+ GojayMethod string
+}
+
+//NewField returns a new field
+func NewField(owner *Struct, field *toolbox.FieldInfo, fieldType *toolbox.TypeInfo) (*Field, error) {
+ typeName := normalizeTypeName(field.TypeName)
+ var result = &Field{
+ IsAnonymous: field.IsAnonymous,
+ Name: field.Name,
+ RawType: field.TypeName,
+ IsPointer: field.IsPointer,
+ Key: getJSONKey(owner.options, field),
+ Receiver: owner.Alias + " *" + owner.TypeInfo.Name,
+ Type: typeName,
+ Mutator: owner.Alias + "." + field.Name,
+ Accessor: owner.Alias + "." + field.Name,
+ ComponentType: field.ComponentType,
+ IsPointerComponent: field.IsPointerComponent,
+ Var: firstLetterToLowercase(field.Name),
+ Init: fmt.Sprintf("%v{}", typeName),
+ TimeLayout: "time.RFC3339",
+ IsSlice: field.IsSlice,
+ PoolName: getPoolName(field.TypeName),
+ Alias: owner.Alias,
+ Reset: "nil",
+ }
+ var err error
+ if field.IsPointer {
+ result.DereferenceModifier = "*"
+ result.Init = "&" + result.Init
+ } else {
+ result.PointerModifier = "&"
+
+ }
+ if field.IsSlice {
+ result.HelperType = getSliceHelperTypeName(field.ComponentType, field.IsPointerComponent)
+ result.PoolName = getPoolName(field.ComponentType)
+ } else if fieldType != nil {
+ result.HelperType = getSliceHelperTypeName(fieldType.Name, field.IsPointerComponent)
+ }
+
+ if options := getTagOptions(field.Tag, "timeLayout"); len(options) > 0 {
+ result.TimeLayout = wrapperIfNeeded(options[0], `"`)
+ } else if options := getTagOptions(field.Tag, "timeFormat"); len(options) > 0 {
+ result.TimeLayout = wrapperIfNeeded(toolbox.DateFormatToLayout(options[0]), `"`)
+ }
+ if strings.Contains(field.Tag, "omitempty") {
+ result.OmitEmpty = "OmitEmpty"
+ }
+ if strings.Contains(field.Tag, "nullempty") {
+ result.OmitEmpty = "NullEmpty"
+ }
+
+ if owner.options.PoolObjects {
+ if field.IsPointer && !strings.HasSuffix(field.TypeName, ".Time") && !strings.Contains(field.TypeName, "sql.Null") {
+ poolName := getPoolName(field.TypeName)
+ result.Init = fmt.Sprintf(`%v.Get().(*%v)`, poolName, field.TypeName)
+ }
+ }
+
+ encodingMethod := field.ComponentType
+ if encodingMethod == "" {
+ encodingMethod = result.Type
+ }
+ result.DecodingMethod = firstLetterToUppercase(encodingMethod)
+ result.EncodingMethod = firstLetterToUppercase(encodingMethod)
+
+ switch typeName {
+ case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64":
+ result.Reset = "0"
+ case "float32", "float64":
+ result.Reset = "0.0"
+ case "string":
+ result.Reset = `""`
+
+ case "bool":
+ result.Reset = "false"
+ default:
+ if field.IsSlice && owner.Type(field.ComponentType) != nil {
+ var itemPointer = ""
+ if !field.IsPointerComponent {
+ itemPointer = "&"
+ }
+ result.ResetDependency, err = expandFieldTemplate(poolSliceInstanceRelease, struct {
+ PoolName string
+ Accessor string
+ PointerModifier string
+ }{PoolName: result.PoolName, Accessor: result.Accessor, PointerModifier: itemPointer})
+ if err != nil {
+ return nil, err
+ }
+
+ } else if field.IsPointer && fieldType != nil {
+ result.ResetDependency, err = expandFieldTemplate(poolInstanceRelease, struct {
+ PoolName string
+ Accessor string
+ }{PoolName: result.PoolName, Accessor: result.Accessor})
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ }
+ if field.IsSlice || field.IsPointer {
+ result.Reset = "nil"
+ }
+
+ if result.IsPointerComponent {
+ result.ComponentInit = "&" + result.ComponentType + "{}"
+ result.RawComponentType = "*" + result.ComponentType
+
+ result.ComponentDereferenceModifier = "*"
+ result.ComponentInitModifier = "&"
+
+ } else {
+ result.ComponentInit = result.ComponentType + "{}"
+ result.RawComponentType = result.ComponentType
+
+ result.ComponentPointerModifier = "&"
+ }
+
+ return result, nil
+}
diff --git a/gojay/codegen/generator.go b/gojay/codegen/generator.go
@@ -0,0 +1,251 @@
+package codegen
+
+import (
+ "fmt"
+ "go/format"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/viant/toolbox"
+)
+
+const gojayPackage = "github.com/francoispqt/gojay"
+
+// Generator holds the content to generate the gojay code
+type Generator struct {
+ fileInfo *toolbox.FileSetInfo
+ types map[string]string
+ structTypes map[string]string
+ sliceTypes map[string]string
+ pooledObjects map[string]string
+ poolInit map[string]string
+ imports map[string]bool
+ filedInit []string
+ Pkg string
+ Code string
+ Init string
+ Imports string
+ options *Options
+}
+
+// Returns the type from the the fileInfo
+func (g *Generator) Type(typeName string) *toolbox.TypeInfo {
+ return g.fileInfo.Type(typeName)
+}
+
+// addImport adds an import package to be printed on the generated code
+func (g *Generator) addImport(pkg string) {
+ g.imports[`"`+pkg+`"`] = true
+}
+
+// we initiate the variables containing the code to be generated
+func (g *Generator) init() {
+ g.filedInit = []string{}
+ g.imports = map[string]bool{}
+ g.pooledObjects = map[string]string{}
+ g.structTypes = map[string]string{}
+ g.sliceTypes = map[string]string{}
+ g.poolInit = map[string]string{}
+ g.addImport(gojayPackage)
+ // if we want pools, add the sync package right away
+ if g.options.PoolObjects {
+ g.addImport("sync")
+ }
+}
+
+// NewGenerator creates a new generator with the given options
+func NewGenerator(options *Options) *Generator {
+ var g = &Generator{}
+ // first we validate the flags
+ if err := options.Validate(); err != nil {
+ panic(err)
+ }
+ g.options = options
+ // we initiate the values on the generator
+ g.init()
+ return g
+}
+
+// Generate generates the gojay implementation code
+func (g *Generator) Generate() error {
+ // first we read the code from which we should find the types
+ if err := g.readPackageCode(g.options.Source); err != nil {
+ return err
+ }
+
+ // then we generate code for the types given
+ for _, rootType := range g.options.Types {
+ if err := g.generateStructCode(rootType); err != nil {
+ return err
+ }
+ }
+
+ //
+ g.Imports = strings.Join(toolbox.MapKeysToStringSlice(g.imports), "\n")
+ return g.writeCode()
+}
+
+func (g *Generator) writeCode() error {
+ var generatedCode = []string{}
+ for _, code := range g.pooledObjects {
+ generatedCode = append(generatedCode, code)
+ }
+ generatedCode = append(generatedCode, "")
+ for _, code := range g.sliceTypes {
+ generatedCode = append(generatedCode, code)
+ }
+ generatedCode = append(generatedCode, "")
+ for _, code := range g.structTypes {
+ generatedCode = append(generatedCode, code)
+ }
+
+ for _, code := range g.poolInit {
+ if g.Init != "" {
+ g.Init += "\n"
+ }
+ g.Init += code
+ }
+ g.Code = strings.Join(generatedCode, "\n")
+
+ expandedCode, err := expandBlockTemplate(fileCode, g)
+ if err != nil {
+ return err
+ }
+
+ code, err := format.Source([]byte(expandedCode))
+
+ if err != nil {
+ return err
+ }
+
+ // code destination is empty, we just print to stdout
+ if g.options.Dest == "" {
+ fmt.Print(string(code))
+ return nil
+ }
+
+ return ioutil.WriteFile(g.options.Dest, code, 0644)
+}
+
+func (g *Generator) generatePrimitiveArray(field *Field) error {
+ key := field.ComponentType + toolbox.AsString(field.IsPointerComponent)
+ if _, ok := g.sliceTypes[key]; ok {
+ return nil
+ }
+ code, err := expandBlockTemplate(baseTypeSlice, field)
+ g.sliceTypes[key] = code
+ return err
+}
+
+func (g *Generator) generateObjectArray(field *Field) error {
+ if _, ok := g.sliceTypes[field.RawComponentType]; ok {
+ return nil
+ }
+
+ if err := g.generateStructCode(field.ComponentType); err != nil {
+ return err
+ }
+ code, err := expandBlockTemplate(structTypeSlice, field)
+ if err != nil {
+ return err
+ }
+ g.sliceTypes[field.RawComponentType] = code
+ return err
+}
+
+func (g *Generator) generateTimeArray(field *Field) error {
+ if _, ok := g.sliceTypes[field.RawComponentType]; ok {
+ return nil
+ }
+
+ code, err := expandBlockTemplate(timeSlice, field)
+ if err != nil {
+ return err
+ }
+ g.sliceTypes[field.RawComponentType] = code
+ return err
+}
+
+func (g *Generator) generateTypedArray(field *Field) error {
+ if _, ok := g.sliceTypes[field.RawComponentType]; ok {
+ return nil
+ }
+
+ code, err := expandBlockTemplate(typeSlice, field)
+ if err != nil {
+ return err
+ }
+ g.sliceTypes[field.RawComponentType] = code
+ return err
+}
+
+func (g *Generator) generatePool(structType string) error {
+ if !g.options.PoolObjects {
+ return nil
+ }
+ var err error
+ if g.pooledObjects[structType], err = expandBlockTemplate(poolVar, struct {
+ PoolName string
+ }{getPoolName(structType)}); err == nil {
+ g.poolInit[structType], err = expandBlockTemplate(poolInit, struct {
+ PoolName string
+ Type string
+ }{getPoolName(structType), structType})
+ }
+ return err
+
+}
+
+func (g *Generator) generateStructCode(structType string) error {
+ structType = normalizeTypeName(structType)
+ typeInfo := g.Type(structType)
+ if typeInfo == nil {
+ return nil
+ }
+ if _, hasCode := g.structTypes[structType]; hasCode {
+ return nil
+ }
+ g.generatePool(structType)
+
+ aStruct := NewStruct(typeInfo, g)
+ code, err := aStruct.Generate()
+
+ if err != nil {
+ return err
+ }
+
+ g.structTypes[structType] = code
+ return nil
+}
+
+func (g *Generator) readPackageCode(pkgPath string) error {
+ p, err := filepath.Abs(pkgPath)
+ if err != nil {
+ return err
+ }
+
+ var f os.FileInfo
+ if f, err = os.Stat(p); err != nil {
+ // path/to/whatever does not exist
+ return err
+ }
+
+ if !f.IsDir() {
+ g.Pkg = filepath.Dir(p)
+ dir, _ := filepath.Split(p)
+ g.fileInfo, err = toolbox.NewFileSetInfo(dir)
+
+ } else {
+ g.Pkg = filepath.Base(p)
+ g.fileInfo, err = toolbox.NewFileSetInfo(p)
+ }
+
+ // if Pkg flag is set use it
+ if g.options.Pkg != "" {
+ g.Pkg = g.options.Pkg
+ }
+
+ return err
+}
diff --git a/gojay/codegen/generator_test.go b/gojay/codegen/generator_test.go
@@ -0,0 +1,72 @@
+package codegen
+
+import (
+ "github.com/stretchr/testify/assert"
+ "github.com/viant/toolbox"
+ "log"
+ "path"
+ "testing"
+)
+
+func TestGenerator_Generate(t *testing.T) {
+
+ parent := path.Join(toolbox.CallerDirectory(3), "test")
+
+ var useCases = []struct {
+ description string
+ options *Options
+ hasError bool
+ }{
+ {
+ description: "basic struct code generation",
+ options: &Options{
+ Source: path.Join(parent, "basic_struct"),
+ Types: []string{"Message"},
+ Dest: path.Join(parent, "basic_struct", "encoding.go"),
+ },
+ },
+
+ {
+ description: "struct with pool code generation",
+ options: &Options{
+ Source: path.Join(parent, "pooled_struct"),
+ Types: []string{"Message"},
+ Dest: path.Join(parent, "pooled_struct", "encoding.go"),
+ PoolObjects: true,
+ },
+ },
+ {
+ description: "struct with embedded type code generation",
+ options: &Options{
+ Source: path.Join(parent, "embedded_struct"),
+ Types: []string{"Message"},
+ Dest: path.Join(parent, "embedded_struct", "encoding.go"),
+ PoolObjects: false,
+ },
+ },
+ {
+ description: "struct with json annotation and time/foarmat|layouat generation",
+ options: &Options{
+ Source: path.Join(parent, "annotated_struct"),
+ Types: []string{"Message"},
+ Dest: path.Join(parent, "annotated_struct", "encoding.go"),
+ PoolObjects: false,
+ TagName: "json",
+ },
+ },
+ }
+
+ for _, useCase := range useCases {
+ gen := NewGenerator(useCase.options)
+ err := gen.Generate()
+ if useCase.hasError {
+ assert.NotNil(t, err, useCase.description)
+ continue
+ }
+ if !assert.Nil(t, err, useCase.description) {
+ log.Fatal(err)
+ continue
+ }
+ }
+
+}
diff --git a/gojay/codegen/helper.go b/gojay/codegen/helper.go
@@ -0,0 +1,89 @@
+package codegen
+
+import (
+ "github.com/viant/toolbox"
+ "reflect"
+ "strings"
+)
+
+func firstLetterToUppercase(text string) string {
+ return strings.ToUpper(string(text[0:1])) + string(text[1:])
+}
+
+func firstLetterToLowercase(text string) string {
+ return strings.ToLower(string(text[0:1])) + string(text[1:])
+}
+
+func extractReceiverAlias(structType string) string {
+ var result = string(structType[0])
+ for i := len(structType) - 1; i > 0; i-- {
+ aChar := string(structType[i])
+ lowerChar := strings.ToLower(aChar)
+ if lowerChar != aChar {
+ result = lowerChar
+ break
+ }
+ }
+ return strings.ToLower(result)
+}
+
+func getTagOptions(tag, key string) []string {
+ if tag == "" {
+ return nil
+ }
+ var structTag = reflect.StructTag(strings.Replace(tag, "`", "", len(tag)))
+ options, ok := structTag.Lookup(key)
+ if !ok {
+ return nil
+ }
+ return strings.Split(options, ",")
+}
+
+func getSliceHelperTypeName(typeName string, isPointer bool) string {
+ if typeName == "" {
+ return ""
+ }
+
+ var pluralName = firstLetterToUppercase(typeName) + "s"
+ if isPointer {
+ pluralName += "Ptr"
+ }
+ return strings.Replace(pluralName, ".", "", -1)
+}
+
+func isSkipable(options *Options, field *toolbox.FieldInfo) bool {
+ if options := getTagOptions(field.Tag, options.TagName); len(options) > 0 {
+ for _, candidate := range options {
+ if candidate == "-" {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+func wrapperIfNeeded(text, wrappingChar string) string {
+ if strings.HasPrefix(text, wrappingChar) {
+ return text
+ }
+ return wrappingChar + text + wrappingChar
+}
+
+func getPoolName(typeName string) string {
+ typeName = strings.Replace(typeName, "*", "", 1)
+ return strings.Replace(typeName+"Pool", ".", "", -1)
+}
+
+func getJSONKey(options *Options, field *toolbox.FieldInfo) string {
+ var key = field.Name
+ if field.Tag != "" {
+ if options := getTagOptions(field.Tag, options.TagName); len(options) > 0 {
+ key = options[0]
+ }
+ }
+ return key
+}
+
+func normalizeTypeName(typeName string) string {
+ return strings.Replace(typeName, "*", "", strings.Count(typeName, "*"))
+}
diff --git a/gojay/codegen/options.go b/gojay/codegen/options.go
@@ -0,0 +1,55 @@
+package codegen
+
+import (
+ "flag"
+ "strings"
+
+ "github.com/go-errors/errors"
+ "github.com/viant/toolbox"
+ "github.com/viant/toolbox/url"
+)
+
+type Options struct {
+ Source string
+ Dest string
+ Types []string
+ PoolObjects bool
+ TagName string
+ Pkg string
+}
+
+func (o *Options) Validate() error {
+ if o.Source == "" {
+ return errors.New("Source was empty")
+ }
+ if len(o.Types) == 0 {
+ return errors.New("Types was empty")
+ }
+ return nil
+}
+
+const (
+ optionKeySource = "s"
+ optionKeyDest = "o"
+ optionKeyTypes = "t"
+ optionKeyTagName = "a"
+ optionKeyPoolObjects = "p"
+ optionKeyPkg = "pkg"
+)
+
+//NewOptionsWithFlagSet creates a new options for the supplide flagset
+func NewOptionsWithFlagSet(set *flag.FlagSet) *Options {
+ toolbox.Dump(set)
+
+ var result = &Options{}
+ result.Dest = set.Lookup(optionKeyDest).Value.String()
+ result.Source = set.Lookup(optionKeySource).Value.String()
+ result.PoolObjects = toolbox.AsBoolean(set.Lookup(optionKeyPoolObjects).Value.String())
+ result.TagName = set.Lookup(optionKeyTagName).Value.String()
+ result.Types = strings.Split(set.Lookup(optionKeyTypes).Value.String(), ",")
+ result.Pkg = set.Lookup(optionKeyPkg).Value.String()
+ if result.Source == "" {
+ result.Source = url.NewResource(".").ParsedURL.Path
+ }
+ return result
+}
diff --git a/gojay/codegen/struct.go b/gojay/codegen/struct.go
@@ -0,0 +1,344 @@
+package codegen
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/viant/toolbox"
+)
+
+type Struct struct {
+ *toolbox.TypeInfo
+ referenced *toolbox.TypeInfo
+ *Generator
+ Alias string
+ Init string
+ Body string
+}
+
+//Generate generates decoderCode + structRelease + encoderCode
+func (s *Struct) Generate() (string, error) {
+ return s.generateEncoding(s.TypeInfo)
+}
+
+func (s *Struct) generateEncoding(structInfo *toolbox.TypeInfo) (string, error) {
+ var initEmbedded, decodingCases, err = s.generateFieldDecoding(structInfo.Fields())
+ if err != nil {
+ return "", err
+ }
+
+ encodingCases, err := s.generateFieldEncoding(structInfo.Fields())
+ if err != nil {
+ return "", err
+ }
+ var resetCode = ""
+ if s.options.PoolObjects {
+ resetCode, err = s.generateReset(structInfo.Fields())
+ if err != nil {
+ return "", err
+ }
+ }
+ var data = struct {
+ Receiver string
+ Alias string
+ InitEmbedded string
+ EncodingCases string
+ DecodingCases string
+ Reset string
+ FieldCount int
+ }{
+ Receiver: s.Alias + " *" + s.Name,
+ DecodingCases: strings.Join(decodingCases, "\n"),
+ EncodingCases: strings.Join(encodingCases, "\n"),
+ FieldCount: len(decodingCases),
+ InitEmbedded: initEmbedded,
+ Reset: resetCode,
+ Alias: s.Alias,
+ }
+ return expandBlockTemplate(encodingStructType, data)
+}
+
+func (s *Struct) generateReset(fields []*toolbox.FieldInfo) (string, error) {
+ fieldReset, err := s.generateFieldReset(fields)
+ if err != nil {
+ return "", nil
+ }
+ return expandBlockTemplate(resetStruct, struct {
+ Reset string
+ Receiver string
+ }{
+ Reset: strings.Join(fieldReset, "\n"),
+ Receiver: s.Alias + " *" + s.Name,
+ })
+}
+
+func (s *Struct) generateFieldReset(fields []*toolbox.FieldInfo) ([]string, error) {
+ fieldReset := []string{}
+ for i := range fields {
+ var templateKey = -1
+ fieldTypeInfo := s.Type(normalizeTypeName(fields[i].TypeName))
+ field, err := NewField(s, fields[i], fieldTypeInfo)
+ if err != nil {
+ return nil, err
+ }
+ if field.IsPointer || field.IsSlice || (fieldTypeInfo != nil && fieldTypeInfo.IsSlice) {
+ templateKey = resetFieldValue
+ } else {
+ switch field.Type {
+ case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64", "string", "bool", "[]string", "[]bool", "[]int", "[]int8", "[]int16", "[]int32", "[]int64", "[]uint", "[]uint8", "[]uint16", "[]uint32", "[]uint64", "[]float32", "[]float64", "[]byte":
+ templateKey = resetFieldValue
+ }
+ }
+ if templateKey != -1 {
+ code, err := expandFieldTemplate(templateKey, field)
+ if err != nil {
+ return nil, err
+ }
+ fieldReset = append(fieldReset, code)
+ }
+ }
+ return fieldReset, nil
+}
+
+func (s *Struct) generateFieldDecoding(fields []*toolbox.FieldInfo) (string, []string, error) {
+
+ fieldCases := []string{}
+ var initCode = ""
+ for i := range fields {
+ if isSkipable(s.options, fields[i]) {
+ continue
+ }
+ var templateKey = -1
+ fieldTypeInfo := s.Type(normalizeTypeName(fields[i].TypeName))
+ field, err := NewField(s, fields[i], fieldTypeInfo)
+ if err != nil {
+ return "", nil, err
+ }
+ if fieldTypeInfo != nil {
+ if err = s.generateStructCode(fieldTypeInfo.Name); err != nil {
+ return "", nil, err
+ }
+ }
+
+ if field.IsAnonymous {
+ if fieldTypeInfo != nil {
+ if field.IsPointer {
+ init, err := expandBlockTemplate(embeddedStructInit, field)
+ if err != nil {
+ return "", nil, err
+ }
+ initCode += init
+ }
+ init, embeddedCases, err := s.generateFieldDecoding(fieldTypeInfo.Fields())
+ if err != nil {
+ return "", nil, err
+ }
+ initCode += init
+ fieldCases = append(fieldCases, embeddedCases...)
+ }
+ continue
+ }
+
+ main:
+ switch field.Type {
+ case "string", "bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64":
+ templateKey = decodeBaseType
+ case "[]string", "[]bool", "[]int", "[]int8", "[]int16", "[]int32", "[]int64", "[]uint", "[]uint8", "[]uint16", "[]uint32", "[]uint64", "[]float32", "[]float64":
+ templateKey = decodeBaseTypeSlice
+ s.generatePrimitiveArray(field)
+ case "[]byte":
+ templateKey = decodeRawType
+ default:
+
+ if fieldTypeInfo != nil {
+ if !(field.IsSlice || fieldTypeInfo.IsSlice) {
+
+ templateKey = decodeStruct
+ break main
+ }
+
+ switch fieldTypeInfo.ComponentType {
+ case "byte":
+ templateKey = decodeRawType
+ break main
+
+ case "string", "bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64":
+ s.generatePrimitiveArray(field)
+ templateKey = decodeBaseTypeSlice
+ break main
+
+ }
+
+ if err = s.generateStructCode(field.ComponentType); err != nil {
+ return "", nil, err
+ }
+
+ templateKey = decodeStructSlice
+ if err = s.generateObjectArray(field); err != nil {
+ return "", nil, err
+ }
+
+ break main
+ } else if field.IsSlice {
+ if f, _, ok := s.typedFieldDecode(field, field.ComponentType); ok {
+ templateKey = decodeStructSlice
+ if err = f(field); err != nil {
+ return "", nil, err
+ }
+ } else {
+ templateKey = decodeStructSlice
+ if err = s.generateObjectArray(field); err != nil {
+ return "", nil, err
+ }
+ }
+ } else if _, k, ok := s.typedFieldDecode(field, field.Type); ok {
+ templateKey = k
+ } else {
+ templateKey = decodeUnknown
+ }
+ }
+ if templateKey != -1 {
+ decodingCase, err := expandFieldTemplate(templateKey, field)
+ if err != nil {
+ return "", nil, err
+ }
+ fieldCases = append(fieldCases, decodingCase)
+ }
+
+ }
+ return initCode, fieldCases, nil
+}
+
+func (s *Struct) generateEmbeddedFieldEncoding(field *Field, fieldTypeInfo *toolbox.TypeInfo) ([]string, error) {
+ var result = []string{}
+ if fieldTypeInfo != nil {
+ embeddedCases, err := s.generateFieldEncoding(fieldTypeInfo.Fields())
+ if err != nil {
+ return nil, err
+ }
+ if field.IsPointer {
+ result = append(result, fmt.Sprintf(" if %v != nil {", field.Accessor))
+ for _, code := range embeddedCases {
+ result = append(result, " "+code)
+ }
+ result = append(result, " }")
+ } else {
+ result = append(result, embeddedCases...)
+ }
+ }
+ return result, nil
+}
+
+func (s *Struct) generateFieldEncoding(fields []*toolbox.FieldInfo) ([]string, error) {
+ fieldCases := []string{}
+ for i := range fields {
+ if isSkipable(s.options, fields[i]) {
+ continue
+ }
+ var templateKey = -1
+ fieldTypeInfo := s.Type(normalizeTypeName(fields[i].TypeName))
+ field, err := NewField(s, fields[i], fieldTypeInfo)
+ if err != nil {
+ return nil, err
+ }
+ if field.IsAnonymous {
+ embedded, err := s.generateEmbeddedFieldEncoding(field, fieldTypeInfo)
+ if err != nil {
+ return nil, err
+ }
+ fieldCases = append(fieldCases, embedded...)
+ continue
+ }
+ main:
+ switch field.Type {
+ case "string", "bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64":
+ templateKey = encodeBaseType
+ case "[]string", "[]bool", "[]int", "[]int8", "[]int16", "[]int32", "[]int64", "[]uint", "[]uint8", "[]uint16", "[]uint32", "[]uint64", "[]float32", "[]float64":
+ templateKey = encodeBaseTypeSlice
+ s.generatePrimitiveArray(field)
+ case "[]byte":
+ templateKey = encodeRawType
+ default:
+ if fieldTypeInfo != nil {
+ if !(field.IsSlice || fieldTypeInfo.IsSlice) {
+ templateKey = encodeStruct
+ break main
+ }
+ switch fieldTypeInfo.ComponentType {
+ case "byte":
+ templateKey = encodeRawType
+ break main
+ case "string", "bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64":
+ templateKey = decodeBaseTypeSlice
+ break main
+ }
+ templateKey = encodeStructSlice
+ break main
+ } else if field.IsSlice {
+ s.typedFieldDecode(field, field.ComponentType)
+ templateKey = encodeStructSlice
+ } else if _, k, ok := s.typedFieldEncode(field, field.Type); ok {
+ templateKey = k
+ } else {
+ templateKey = encodeUnknown
+ }
+ }
+ if templateKey != -1 {
+ decodingCase, err := expandFieldTemplate(templateKey, field)
+ if err != nil {
+ return nil, err
+ }
+ fieldCases = append(fieldCases, decodingCase)
+ }
+
+ }
+ return fieldCases, nil
+}
+
+var sqlNullTypes = []string{
+ "Bool",
+ "Float64",
+ "Int64",
+ "String",
+ "Time",
+}
+
+func (s *Struct) typedFieldEncode(field *Field, typeName string) (func(*Field) error, int, bool) {
+ if strings.Contains(typeName, "time.Time") {
+ return s.generateTimeArray, encodeTime, true
+ } else if strings.Contains(typeName, "sql.Null") {
+ for _, nullType := range sqlNullTypes {
+ if strings.Contains(typeName, nullType) {
+ field.NullType = nullType
+ field.GojayMethod = "SQLNull" + nullType
+ }
+ }
+ return s.generateTypedArray, encodeSQLNull, true
+ }
+ return nil, 0, false
+}
+
+func (s *Struct) typedFieldDecode(field *Field, typeName string) (func(*Field) error, int, bool) {
+ if strings.Contains(typeName, "time.Time") {
+ s.addImport("time")
+ return s.generateTimeArray, decodeTime, true
+ } else if strings.Contains(typeName, "sql.Null") {
+ for _, nullType := range sqlNullTypes {
+ if strings.Contains(typeName, nullType) {
+ field.NullType = nullType
+ field.GojayMethod = "SQLNull" + nullType
+ }
+ }
+ s.addImport("database/sql")
+ return s.generateTypedArray, decodeSQLNull, true
+ }
+ return nil, 0, false
+}
+
+func NewStruct(info *toolbox.TypeInfo, generator *Generator) *Struct {
+ return &Struct{
+ TypeInfo: info,
+ Generator: generator,
+ Alias: extractReceiverAlias(info.Name),
+ }
+}
diff --git a/gojay/codegen/template.go b/gojay/codegen/template.go
@@ -0,0 +1,325 @@
+package codegen
+
+import (
+ "bytes"
+ "fmt"
+ "text/template"
+)
+
+const (
+ decodeBaseType = iota
+ encodeBaseType
+ decodeBaseTypeSlice
+ encodeBaseTypeSlice
+ decodeRawType
+ encodeRawType
+ decodeStruct
+ encodeStruct
+
+ decodeStructSlice
+ encodeStructSlice
+ decodeTime
+ encodeTime
+
+ decodeSQLNull
+ encodeSQLNull
+
+ decodeUnknown
+ encodeUnknown
+
+ resetFieldValue
+ poolInstanceRelease
+ poolSliceInstanceRelease
+)
+
+var fieldTemplate = map[int]string{
+ decodeBaseType: ` case "{{.Key}}":
+{{if .IsPointer}} var value {{.Type}}
+ err := dec.{{.DecodingMethod}}(&value)
+ if err == nil {
+ {{.Accessor}} = &value
+ }
+ return err
+{{else}} return dec.{{.DecodingMethod}}(&{{.Accessor}}){{end}}
+`,
+ encodeBaseType: ` enc.{{.EncodingMethod}}Key{{.OmitEmpty}}("{{.Key}}", {{.DereferenceModifier}}{{.Accessor}})`,
+
+ decodeBaseTypeSlice: ` case "{{.Key}}":
+ var aSlice = {{.HelperType}}{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ {{.Mutator}} = {{.RawType}}(aSlice)
+ }
+ return err
+`,
+ encodeBaseTypeSlice: ` var {{.Var}}Slice = {{.HelperType}}({{.Accessor}})
+ enc.ArrayKey{{.OmitEmpty}}("{{.Key}}",{{.Var}}Slice)`,
+
+ decodeRawType: ` case "{{.Key}}":
+ var value = gojay.EmbeddedJSON{}
+ err := dec.AddEmbeddedJSON(&value)
+ if err == nil && len(value) > 0 {
+ {{.Mutator}} = {{.Type}}(value)
+ }
+ return err
+`,
+
+ encodeRawType: ` var {{.Var}}Slice = gojay.EmbeddedJSON({{.Accessor}})
+ enc.AddEmbeddedJSONKey{{.OmitEmpty}}("{{.Key}}", &{{.Var}}Slice)`,
+ decodeStruct: ` case "{{.Key}}":{{if .IsPointer}}
+ var value = {{.Init}}
+ err := dec.Object(value)
+ if err == nil {
+ {{.Mutator}} = value
+ }
+{{else}}
+ err := dec.Object(&{{.Mutator}})
+{{end}}
+ return err
+`,
+ encodeStruct: ` enc.ObjectKey{{.OmitEmpty}}("{{.Key}}", {{.PointerModifier}}{{.Accessor}})`,
+
+ decodeStructSlice: ` case "{{.Key}}":
+ var aSlice = {{.HelperType}}{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ {{.Mutator}} = {{.RawType}}(aSlice)
+ }
+ return err
+ `,
+
+ encodeStructSlice: ` var {{.Var}}Slice = {{.HelperType}}({{.Accessor}})
+ enc.ArrayKey{{.OmitEmpty}}("{{.Key}}", {{.DereferenceModifier}}{{.Var}}Slice)`,
+
+ decodeTime: ` case "{{.Key}}":
+ var format = {{.TimeLayout}}
+ var value = {{.Init}}
+ err := dec.Time({{.PointerModifier}}value, format)
+ if err == nil {
+ {{.Mutator}} = value
+ }
+ return err
+`,
+
+ encodeTime: `{{if .IsPointer}} if {{.Accessor}} != nil {
+ enc.TimeKey("{{.Key}}", {{.PointerModifier}}{{.Accessor}}, {{.TimeLayout}})
+ }{{else}} enc.TimeKey("{{.Key}}", {{.PointerModifier}}{{.Accessor}}, {{.TimeLayout}}){{end}}`,
+ decodeSQLNull: ` case "{{.Key}}":
+ var value = {{.Init}}
+ err := dec.SQLNull{{.NullType}}({{.PointerModifier}}value)
+ if err == nil {
+ {{.Mutator}} = value
+ }
+ return err
+`,
+ encodeSQLNull: `{{if .IsPointer}} if {{.Accessor}} != nil {
+ enc.SQLNull{{.NullType}}Key{{.OmitEmpty}}("{{.Key}}", {{.PointerModifier}}{{.Accessor}})
+ }{{else}} enc.SQLNull{{.NullType}}Key{{.OmitEmpty}}("{{.Key}}", {{.PointerModifier}}{{.Accessor}}){{end}}`,
+ decodeUnknown: ` case "{{.Key}}":
+ //TODO
+ //dec.Any({{.Accessor}})
+ return nil
+`,
+ encodeUnknown: `
+ //TODO
+ //enc.Any({{.Accessor}})
+
+`,
+ resetFieldValue: `{{if .ResetDependency}}{{.ResetDependency}}
+{{end}} {{.Mutator}} = {{.Reset}}`,
+ poolInstanceRelease: ` {{.PoolName}}.Put({{.Accessor}})`,
+
+ poolSliceInstanceRelease: ` for i := range {{.Accessor}} {
+ {{.Accessor}}[i].Reset()
+ {{.PoolName}}.Put({{.PointerModifier}}{{.Accessor}}[i])
+ }`,
+}
+
+const (
+ fileCode = iota
+ encodingStructType
+ baseTypeSlice
+ structTypeSlice
+ resetStruct
+ poolVar
+ poolInit
+ embeddedStructInit
+ timeSlice
+ typeSlice
+)
+
+var blockTemplate = map[int]string{
+ fileCode: `// Code generated by Gojay. DO NOT EDIT.
+
+
+package {{.Pkg}}
+
+import (
+ {{.Imports}}
+)
+{{if .Init}}
+func init() {
+{{.Init}}
+}
+{{end}}
+{{.Code}}
+`,
+ encodingStructType: `// MarshalJSONObject implements MarshalerJSONObject
+func ({{.Receiver}}) MarshalJSONObject(enc *gojay.Encoder) {
+{{.EncodingCases}}
+}
+
+// IsNil checks if instance is nil
+func ({{.Receiver}}) IsNil() bool {
+ return {{.Alias}} == nil
+}
+
+// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
+func ({{.Receiver}}) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
+{{.InitEmbedded}}
+ switch k {
+{{.DecodingCases}}
+ }
+ return nil
+}
+
+// NKeys returns the number of keys to unmarshal
+func ({{.Receiver}}) NKeys() int { return {{.FieldCount}} }
+
+{{.Reset}}
+
+`,
+
+ baseTypeSlice: `
+
+type {{.HelperType}} {{.RawType}}
+
+// UnmarshalJSONArray decodes JSON array elements into slice
+func (a *{{.HelperType}}) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value {{.ComponentType}}
+ if err := dec.{{.DecodingMethod}}(&value); err != nil {
+ return err
+ }
+ *a = append(*a, {{.ComponentInitModifier}}value)
+ return nil
+}
+
+// MarshalJSONArray encodes arrays into JSON
+func (a {{.HelperType}}) MarshalJSONArray(enc *gojay.Encoder) {
+ for _, item := range a {
+ enc.{{.EncodingMethod}}({{.ComponentDereferenceModifier}}item)
+ }
+}
+
+// IsNil checks if array is nil
+func (a {{.HelperType}}) IsNil() bool {
+ return len(a) == 0
+}
+`,
+
+ structTypeSlice: `
+type {{.HelperType}} {{.RawType}}
+
+func (s *{{.HelperType}}) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value = {{.ComponentInit}}
+ if err := dec.Object({{.ComponentPointerModifier}}value); err != nil {
+ return err
+ }
+ *s = append(*s, value)
+ return nil
+}
+
+func (s {{.HelperType}}) MarshalJSONArray(enc *gojay.Encoder) {
+ for i := range s {
+ enc.Object({{.ComponentPointerModifier}}s[i])
+ }
+}
+
+func (s {{.HelperType}}) IsNil() bool {
+ return len(s) == 0
+}
+`,
+ typeSlice: `
+type {{.HelperType}} {{.RawType}}
+
+func (s *{{.HelperType}}) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value = {{.ComponentInit}}
+ if err := dec.{{.GojayMethod}}({{.ComponentPointerModifier}}value); err != nil {
+ return err
+ }
+ *s = append(*s, value)
+ return nil
+}
+
+func (s {{.HelperType}}) MarshalJSONArray(enc *gojay.Encoder) {
+ for i := range s {
+ enc.{{.GojayMethod}}({{.ComponentPointerModifier}}s[i])
+ }
+}
+
+func (s {{.HelperType}}) IsNil() bool {
+ return len(s) == 0
+}
+`,
+ timeSlice: `
+type {{.HelperType}} {{.RawType}}
+
+func (s *{{.HelperType}}) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value = {{.ComponentInit}}
+ if err := dec.Time({{.ComponentPointerModifier}}value, {{.TimeLayout}}); err != nil {
+ return err
+ }
+ *s = append(*s, value)
+ return nil
+}
+
+func (s {{.HelperType}}) MarshalJSONArray(enc *gojay.Encoder) {
+ for i := range s {
+ enc.Time({{.ComponentPointerModifier}}s[i], {{.TimeLayout}})
+ }
+}
+
+func (s {{.HelperType}}) IsNil() bool {
+ return len(s) == 0
+}
+`,
+ resetStruct: `
+// Reset reset fields
+func ({{.Receiver}}) Reset() {
+{{.Reset}}
+}
+`,
+
+ poolVar: `var {{.PoolName}} *sync.Pool`,
+ poolInit: ` {{.PoolName}} = &sync.Pool {
+ New: func()interface{} {
+ return &{{.Type}}{}
+ },
+ }`,
+ embeddedStructInit: `if {{.Accessor}} == nil {
+ {{.Accessor}} = {{.Init}}
+ }`,
+}
+
+func expandTemplate(namespace string, dictionary map[int]string, key int, data interface{}) (string, error) {
+ var id = fmt.Sprintf("%v_%v", namespace, key)
+ textTemplate, ok := dictionary[key]
+ if !ok {
+ return "", fmt.Errorf("failed to lookup template for %v.%v", namespace, key)
+ }
+ temlate, err := template.New(id).Parse(textTemplate)
+ if err != nil {
+ return "", fmt.Errorf("fiailed to parse template %v %v, due to %v", namespace, key, err)
+ }
+ writer := new(bytes.Buffer)
+ err = temlate.Execute(writer, data)
+ return writer.String(), err
+}
+
+func expandFieldTemplate(key int, data interface{}) (string, error) {
+ return expandTemplate("fieldTemplate", fieldTemplate, key, data)
+}
+
+func expandBlockTemplate(key int, data interface{}) (string, error) {
+ return expandTemplate("blockTemplate", blockTemplate, key, data)
+}
diff --git a/codegen/template_test.go b/gojay/codegen/template_test.go
diff --git a/gojay/codegen/test/annotated_struct/encoding.go b/gojay/codegen/test/annotated_struct/encoding.go
@@ -0,0 +1,289 @@
+// Code generated by Gojay. DO NOT EDIT.
+
+package annotated_struct
+
+import (
+ "database/sql"
+ "github.com/francoispqt/gojay"
+ "time"
+)
+
+type Ints []int
+
+// UnmarshalJSONArray decodes JSON array elements into slice
+func (a *Ints) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value int
+ if err := dec.Int(&value); err != nil {
+ return err
+ }
+ *a = append(*a, value)
+ return nil
+}
+
+// MarshalJSONArray encodes arrays into JSON
+func (a Ints) MarshalJSONArray(enc *gojay.Encoder) {
+ for _, item := range a {
+ enc.Int(item)
+ }
+}
+
+// IsNil checks if array is nil
+func (a Ints) IsNil() bool {
+ return len(a) == 0
+}
+
+type Float32s []float32
+
+// UnmarshalJSONArray decodes JSON array elements into slice
+func (a *Float32s) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value float32
+ if err := dec.Float32(&value); err != nil {
+ return err
+ }
+ *a = append(*a, value)
+ return nil
+}
+
+// MarshalJSONArray encodes arrays into JSON
+func (a Float32s) MarshalJSONArray(enc *gojay.Encoder) {
+ for _, item := range a {
+ enc.Float32(item)
+ }
+}
+
+// IsNil checks if array is nil
+func (a Float32s) IsNil() bool {
+ return len(a) == 0
+}
+
+type SubMessagesPtr []*SubMessage
+
+func (s *SubMessagesPtr) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value = &SubMessage{}
+ if err := dec.Object(value); err != nil {
+ return err
+ }
+ *s = append(*s, value)
+ return nil
+}
+
+func (s SubMessagesPtr) MarshalJSONArray(enc *gojay.Encoder) {
+ for i := range s {
+ enc.Object(s[i])
+ }
+}
+
+func (s SubMessagesPtr) IsNil() bool {
+ return len(s) == 0
+}
+
+type SubMessages []SubMessage
+
+func (s *SubMessages) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value = SubMessage{}
+ if err := dec.Object(&value); err != nil {
+ return err
+ }
+ *s = append(*s, value)
+ return nil
+}
+
+func (s SubMessages) MarshalJSONArray(enc *gojay.Encoder) {
+ for i := range s {
+ enc.Object(&s[i])
+ }
+}
+
+func (s SubMessages) IsNil() bool {
+ return len(s) == 0
+}
+
+// MarshalJSONObject implements MarshalerJSONObject
+func (p *Payload) MarshalJSONObject(enc *gojay.Encoder) {
+
+}
+
+// IsNil checks if instance is nil
+func (p *Payload) IsNil() bool {
+ return p == nil
+}
+
+// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
+func (p *Payload) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
+
+ switch k {
+
+ }
+ return nil
+}
+
+// NKeys returns the number of keys to unmarshal
+func (p *Payload) NKeys() int { return 0 }
+
+// MarshalJSONObject implements MarshalerJSONObject
+func (m *Message) MarshalJSONObject(enc *gojay.Encoder) {
+ enc.IntKey("id", m.Id)
+ enc.StringKey("name", m.Name)
+ enc.Float64Key("price", m.Price)
+ var intsSlice = Ints(m.Ints)
+ enc.ArrayKey("ints", intsSlice)
+ var floatsSlice = Float32s(m.Floats)
+ enc.ArrayKey("floats", floatsSlice)
+ enc.ObjectKey("subMessageX", m.SubMessageX)
+ var messagesXSlice = SubMessagesPtr(m.MessagesX)
+ enc.ArrayKey("messagesX", messagesXSlice)
+ enc.ObjectKey("SubMessageY", &m.SubMessageY)
+ var messagesYSlice = SubMessages(m.MessagesY)
+ enc.ArrayKey("MessagesY", messagesYSlice)
+ enc.BoolKey("enabled", *m.IsTrue)
+ var payloadSlice = gojay.EmbeddedJSON(m.Payload)
+ enc.AddEmbeddedJSONKey("data", &payloadSlice)
+ if m.SQLNullString != nil {
+ enc.SQLNullStringKey("sqlNullString", m.SQLNullString)
+ }
+}
+
+// IsNil checks if instance is nil
+func (m *Message) IsNil() bool {
+ return m == nil
+}
+
+// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
+func (m *Message) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
+
+ switch k {
+ case "id":
+ return dec.Int(&m.Id)
+
+ case "name":
+ return dec.String(&m.Name)
+
+ case "price":
+ return dec.Float64(&m.Price)
+
+ case "ints":
+ var aSlice = Ints{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.Ints = []int(aSlice)
+ }
+ return err
+
+ case "floats":
+ var aSlice = Float32s{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.Floats = []float32(aSlice)
+ }
+ return err
+
+ case "subMessageX":
+ var value = &SubMessage{}
+ err := dec.Object(value)
+ if err == nil {
+ m.SubMessageX = value
+ }
+
+ return err
+
+ case "messagesX":
+ var aSlice = SubMessagesPtr{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.MessagesX = []*SubMessage(aSlice)
+ }
+ return err
+
+ case "SubMessageY":
+ err := dec.Object(&m.SubMessageY)
+
+ return err
+
+ case "MessagesY":
+ var aSlice = SubMessages{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.MessagesY = []SubMessage(aSlice)
+ }
+ return err
+
+ case "enabled":
+ var value bool
+ err := dec.Bool(&value)
+ if err == nil {
+ m.IsTrue = &value
+ }
+ return err
+
+ case "data":
+ var value = gojay.EmbeddedJSON{}
+ err := dec.AddEmbeddedJSON(&value)
+ if err == nil && len(value) > 0 {
+ m.Payload = Payload(value)
+ }
+ return err
+
+ case "sqlNullString":
+ var value = &sql.NullString{}
+ err := dec.SQLNullString(value)
+ if err == nil {
+ m.SQLNullString = value
+ }
+ return err
+
+ }
+ return nil
+}
+
+// NKeys returns the number of keys to unmarshal
+func (m *Message) NKeys() int { return 12 }
+
+// MarshalJSONObject implements MarshalerJSONObject
+func (m *SubMessage) MarshalJSONObject(enc *gojay.Encoder) {
+ enc.IntKey("id", m.Id)
+ enc.StringKey("description", m.Description)
+ enc.TimeKey("startDate", &m.StartTime, "2006-01-02 15:04:05")
+ if m.EndTime != nil {
+ enc.TimeKey("endDate", m.EndTime, "2006-01-02 15:04:05")
+ }
+}
+
+// IsNil checks if instance is nil
+func (m *SubMessage) IsNil() bool {
+ return m == nil
+}
+
+// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
+func (m *SubMessage) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
+
+ switch k {
+ case "id":
+ return dec.Int(&m.Id)
+
+ case "description":
+ return dec.String(&m.Description)
+
+ case "startDate":
+ var format = "2006-01-02 15:04:05"
+ var value = time.Time{}
+ err := dec.Time(&value, format)
+ if err == nil {
+ m.StartTime = value
+ }
+ return err
+
+ case "endDate":
+ var format = "2006-01-02 15:04:05"
+ var value = &time.Time{}
+ err := dec.Time(value, format)
+ if err == nil {
+ m.EndTime = value
+ }
+ return err
+
+ }
+ return nil
+}
+
+// NKeys returns the number of keys to unmarshal
+func (m *SubMessage) NKeys() int { return 4 }
diff --git a/gojay/codegen/test/annotated_struct/encoding_test.go b/gojay/codegen/test/annotated_struct/encoding_test.go
@@ -0,0 +1,126 @@
+package annotated_struct
+
+import (
+ "bytes"
+ "database/sql"
+ "log"
+ "testing"
+
+ "github.com/francoispqt/gojay"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+var isTrue = true
+var msg = &Message{
+ Id: 1022,
+ Name: "name acc",
+ Price: 13.3,
+ Ints: []int{1, 2, 5},
+ Floats: []float32{2.3, 4.6, 7.4},
+ SubMessageX: &SubMessage{
+ Id: 102,
+ Description: "abcd",
+ },
+ MessagesX: []*SubMessage{
+ &SubMessage{
+ Id: 2102,
+ Description: "abce",
+ },
+ },
+ SubMessageY: SubMessage{
+ Id: 3102,
+ Description: "abcf",
+ },
+ MessagesY: []SubMessage{
+ SubMessage{
+ Id: 5102,
+ Description: "abcg",
+ },
+ SubMessage{
+ Id: 5106,
+ Description: "abcgg",
+ },
+ },
+ IsTrue: &isTrue,
+ Payload: []byte(`"123"`),
+ SQLNullString: &sql.NullString{
+ String: "test",
+ Valid: true,
+ },
+}
+
+var jsonData = `{
+ "id": 1022,
+ "name": "name acc",
+ "price": 13.3,
+ "ints": [
+ 1,
+ 2,
+ 5
+ ],
+ "floats": [
+ 2.3,
+ 4.6,
+ 7.4
+ ],
+ "subMessageX": {
+ "id": 102,
+ "description": "abcd",
+ "startDate": "0001-01-01 00:00:00"
+ },
+ "messagesX": [
+ {
+ "id": 2102,
+ "description": "abce",
+ "startDate": "0001-01-01 00:00:00"
+ }
+ ],
+ "SubMessageY": {
+ "id": 3102,
+ "description": "abcf",
+ "startDate": "0001-01-01 00:00:00"
+ },
+ "MessagesY": [
+ {
+ "id": 5102,
+ "description": "abcg",
+ "startDate": "0001-01-01 00:00:00"
+ },
+ {
+ "id": 5106,
+ "description": "abcgg",
+ "startDate": "0001-01-01 00:00:00"
+ }
+ ],
+ "enabled": true,
+ "data": "123",
+ "sqlNullString": "test"
+}`
+
+func TestMessage_Unmarshal(t *testing.T) {
+
+ var err error
+ var data = []byte(jsonData)
+ message := &Message{}
+ err = gojay.UnmarshalJSONObject(data, message)
+ if !assert.Nil(t, err) {
+ log.Fatal(err)
+ }
+ require.Equal(
+ t,
+ msg,
+ message,
+ )
+}
+
+func TestMessage_Marshal(t *testing.T) {
+ var err error
+ var writer = new(bytes.Buffer)
+ encoder := gojay.NewEncoder(writer)
+ err = encoder.Encode(msg)
+ assert.Nil(t, err)
+ var JSON = writer.String()
+ require.JSONEq(t, jsonData, JSON)
+
+}
diff --git a/gojay/codegen/test/annotated_struct/message.go b/gojay/codegen/test/annotated_struct/message.go
@@ -0,0 +1,21 @@
+package annotated_struct
+
+import "database/sql"
+
+type Payload []byte
+
+type Message struct {
+ Id int `json:"id"`
+ Name string `json:"name"`
+ Price float64 `json:"price"`
+ Ints []int `json:"ints"`
+ Floats []float32 `json:"floats"`
+ SubMessageX *SubMessage `json:"subMessageX"`
+ MessagesX []*SubMessage `json:"messagesX"`
+ SubMessageY SubMessage
+ MessagesY []SubMessage
+ IsTrue *bool `json:"enabled"`
+ Payload Payload `json:"data"`
+ Ignore string `json:"-"`
+ SQLNullString *sql.NullString `json:"sqlNullString"`
+}
diff --git a/gojay/codegen/test/annotated_struct/sub_message.go b/gojay/codegen/test/annotated_struct/sub_message.go
@@ -0,0 +1,10 @@
+package annotated_struct
+
+import "time"
+
+type SubMessage struct {
+ Id int `json:"id"`
+ Description string `json:"description"`
+ StartTime time.Time `json:"startDate" timeFormat:"yyyy-MM-dd HH:mm:ss"`
+ EndTime *time.Time `json:"endDate" timeLayout:"2006-01-02 15:04:05"`
+}
diff --git a/gojay/codegen/test/basic_struct/encoding.go b/gojay/codegen/test/basic_struct/encoding.go
@@ -0,0 +1,267 @@
+// Code generated by Gojay. DO NOT EDIT.
+
+package basic_struct
+
+import (
+ "database/sql"
+ "github.com/francoispqt/gojay"
+ "time"
+)
+
+type SubMessagesPtr []*SubMessage
+
+func (s *SubMessagesPtr) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value = &SubMessage{}
+ if err := dec.Object(value); err != nil {
+ return err
+ }
+ *s = append(*s, value)
+ return nil
+}
+
+func (s SubMessagesPtr) MarshalJSONArray(enc *gojay.Encoder) {
+ for i := range s {
+ enc.Object(s[i])
+ }
+}
+
+func (s SubMessagesPtr) IsNil() bool {
+ return len(s) == 0
+}
+
+type SubMessages []SubMessage
+
+func (s *SubMessages) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value = SubMessage{}
+ if err := dec.Object(&value); err != nil {
+ return err
+ }
+ *s = append(*s, value)
+ return nil
+}
+
+func (s SubMessages) MarshalJSONArray(enc *gojay.Encoder) {
+ for i := range s {
+ enc.Object(&s[i])
+ }
+}
+
+func (s SubMessages) IsNil() bool {
+ return len(s) == 0
+}
+
+type Ints []int
+
+// UnmarshalJSONArray decodes JSON array elements into slice
+func (a *Ints) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value int
+ if err := dec.Int(&value); err != nil {
+ return err
+ }
+ *a = append(*a, value)
+ return nil
+}
+
+// MarshalJSONArray encodes arrays into JSON
+func (a Ints) MarshalJSONArray(enc *gojay.Encoder) {
+ for _, item := range a {
+ enc.Int(item)
+ }
+}
+
+// IsNil checks if array is nil
+func (a Ints) IsNil() bool {
+ return len(a) == 0
+}
+
+type Float32s []float32
+
+// UnmarshalJSONArray decodes JSON array elements into slice
+func (a *Float32s) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value float32
+ if err := dec.Float32(&value); err != nil {
+ return err
+ }
+ *a = append(*a, value)
+ return nil
+}
+
+// MarshalJSONArray encodes arrays into JSON
+func (a Float32s) MarshalJSONArray(enc *gojay.Encoder) {
+ for _, item := range a {
+ enc.Float32(item)
+ }
+}
+
+// IsNil checks if array is nil
+func (a Float32s) IsNil() bool {
+ return len(a) == 0
+}
+
+// MarshalJSONObject implements MarshalerJSONObject
+func (m *SubMessage) MarshalJSONObject(enc *gojay.Encoder) {
+ enc.IntKey("Id", m.Id)
+ enc.StringKey("Description", m.Description)
+ enc.TimeKey("StartTime", &m.StartTime, time.RFC3339)
+ if m.EndTime != nil {
+ enc.TimeKey("EndTime", m.EndTime, time.RFC3339)
+ }
+}
+
+// IsNil checks if instance is nil
+func (m *SubMessage) IsNil() bool {
+ return m == nil
+}
+
+// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
+func (m *SubMessage) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
+
+ switch k {
+ case "Id":
+ return dec.Int(&m.Id)
+
+ case "Description":
+ return dec.String(&m.Description)
+
+ case "StartTime":
+ var format = time.RFC3339
+ var value = time.Time{}
+ err := dec.Time(&value, format)
+ if err == nil {
+ m.StartTime = value
+ }
+ return err
+
+ case "EndTime":
+ var format = time.RFC3339
+ var value = &time.Time{}
+ err := dec.Time(value, format)
+ if err == nil {
+ m.EndTime = value
+ }
+ return err
+
+ }
+ return nil
+}
+
+// NKeys returns the number of keys to unmarshal
+func (m *SubMessage) NKeys() int { return 4 }
+
+// MarshalJSONObject implements MarshalerJSONObject
+func (m *Message) MarshalJSONObject(enc *gojay.Encoder) {
+ enc.IntKey("Id", m.Id)
+ enc.StringKey("Name", m.Name)
+ enc.Float64Key("Price", m.Price)
+ var intsSlice = Ints(m.Ints)
+ enc.ArrayKey("Ints", intsSlice)
+ var floatsSlice = Float32s(m.Floats)
+ enc.ArrayKey("Floats", floatsSlice)
+ enc.ObjectKey("SubMessageX", m.SubMessageX)
+ var messagesXSlice = SubMessagesPtr(m.MessagesX)
+ enc.ArrayKey("MessagesX", messagesXSlice)
+ enc.ObjectKey("SubMessageY", &m.SubMessageY)
+ var messagesYSlice = SubMessages(m.MessagesY)
+ enc.ArrayKey("MessagesY", messagesYSlice)
+ enc.BoolKey("IsTrue", *m.IsTrue)
+ var payloadSlice = gojay.EmbeddedJSON(m.Payload)
+ enc.AddEmbeddedJSONKey("Payload", &payloadSlice)
+ if m.SQLNullString != nil {
+ enc.SQLNullStringKey("SQLNullString", m.SQLNullString)
+ }
+}
+
+// IsNil checks if instance is nil
+func (m *Message) IsNil() bool {
+ return m == nil
+}
+
+// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
+func (m *Message) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
+
+ switch k {
+ case "Id":
+ return dec.Int(&m.Id)
+
+ case "Name":
+ return dec.String(&m.Name)
+
+ case "Price":
+ return dec.Float64(&m.Price)
+
+ case "Ints":
+ var aSlice = Ints{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.Ints = []int(aSlice)
+ }
+ return err
+
+ case "Floats":
+ var aSlice = Float32s{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.Floats = []float32(aSlice)
+ }
+ return err
+
+ case "SubMessageX":
+ var value = &SubMessage{}
+ err := dec.Object(value)
+ if err == nil {
+ m.SubMessageX = value
+ }
+
+ return err
+
+ case "MessagesX":
+ var aSlice = SubMessagesPtr{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.MessagesX = []*SubMessage(aSlice)
+ }
+ return err
+
+ case "SubMessageY":
+ err := dec.Object(&m.SubMessageY)
+
+ return err
+
+ case "MessagesY":
+ var aSlice = SubMessages{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.MessagesY = []SubMessage(aSlice)
+ }
+ return err
+
+ case "IsTrue":
+ var value bool
+ err := dec.Bool(&value)
+ if err == nil {
+ m.IsTrue = &value
+ }
+ return err
+
+ case "Payload":
+ var value = gojay.EmbeddedJSON{}
+ err := dec.AddEmbeddedJSON(&value)
+ if err == nil && len(value) > 0 {
+ m.Payload = []byte(value)
+ }
+ return err
+
+ case "SQLNullString":
+ var value = &sql.NullString{}
+ err := dec.SQLNullString(value)
+ if err == nil {
+ m.SQLNullString = value
+ }
+ return err
+
+ }
+ return nil
+}
+
+// NKeys returns the number of keys to unmarshal
+func (m *Message) NKeys() int { return 12 }
diff --git a/gojay/codegen/test/basic_struct/encoding_test.go b/gojay/codegen/test/basic_struct/encoding_test.go
@@ -0,0 +1,118 @@
+package basic_struct
+
+import (
+ "bytes"
+ "database/sql"
+ "testing"
+
+ "github.com/francoispqt/gojay"
+ "github.com/stretchr/testify/require"
+)
+
+var isTrue = true
+var msg = &Message{
+ Id: 1022,
+ Name: "name acc",
+ Price: 13.3,
+ Ints: []int{1, 2, 5},
+ Floats: []float32{2.3, 4.6, 7.4},
+ SubMessageX: &SubMessage{
+ Id: 102,
+ Description: "abcd",
+ },
+ MessagesX: []*SubMessage{
+ &SubMessage{
+ Id: 2102,
+ Description: "abce",
+ },
+ },
+ SubMessageY: SubMessage{
+ Id: 3102,
+ Description: "abcf",
+ },
+ MessagesY: []SubMessage{
+ SubMessage{
+ Id: 5102,
+ Description: "abcg",
+ },
+ SubMessage{
+ Id: 5106,
+ Description: "abcgg",
+ },
+ },
+ IsTrue: &isTrue,
+ Payload: []byte(`"123"`),
+ SQLNullString: &sql.NullString{
+ String: "test",
+ Valid: true,
+ },
+}
+
+var jsonData = `{
+ "Id": 1022,
+ "Name": "name acc",
+ "Price": 13.3,
+ "Ints": [
+ 1,
+ 2,
+ 5
+ ],
+ "Floats": [
+ 2.3,
+ 4.6,
+ 7.4
+ ],
+ "SubMessageX": {
+ "Id": 102,
+ "Description": "abcd",
+ "StartTime": "0001-01-01T00:00:00Z"
+ },
+ "MessagesX": [
+ {
+ "Id": 2102,
+ "Description": "abce",
+ "StartTime": "0001-01-01T00:00:00Z"
+ }
+ ],
+ "SubMessageY": {
+ "Id": 3102,
+ "Description": "abcf",
+ "StartTime": "0001-01-01T00:00:00Z"
+ },
+ "MessagesY": [
+ {
+ "Id": 5102,
+ "Description": "abcg",
+ "StartTime": "0001-01-01T00:00:00Z"
+ },
+ {
+ "Id": 5106,
+ "Description": "abcgg",
+ "StartTime": "0001-01-01T00:00:00Z"
+ }
+ ],
+ "IsTrue": true,
+ "Payload": "123",
+ "SQLNullString": "test"
+}`
+
+func TestMessage_Unmarshal(t *testing.T) {
+ var err error
+ var data = []byte(jsonData)
+ message := &Message{}
+ err = gojay.UnmarshalJSONObject(data, message)
+ require.Nil(t, err)
+ require.Equal(t, msg, message)
+}
+
+func TestMessage_Marshal(t *testing.T) {
+ var writer = new(bytes.Buffer)
+
+ encoder := gojay.NewEncoder(writer)
+ var err = encoder.Encode(msg)
+
+ require.Nil(t, err)
+ var JSON = writer.String()
+
+ require.JSONEq(t, jsonData, JSON)
+}
diff --git a/gojay/codegen/test/basic_struct/message.go b/gojay/codegen/test/basic_struct/message.go
@@ -0,0 +1,18 @@
+package basic_struct
+
+import "database/sql"
+
+type Message struct {
+ Id int
+ Name string
+ Price float64
+ Ints []int
+ Floats []float32
+ SubMessageX *SubMessage
+ MessagesX []*SubMessage
+ SubMessageY SubMessage
+ MessagesY []SubMessage
+ IsTrue *bool
+ Payload []byte
+ SQLNullString *sql.NullString
+}
diff --git a/gojay/codegen/test/basic_struct/sub_message.go b/gojay/codegen/test/basic_struct/sub_message.go
@@ -0,0 +1,10 @@
+package basic_struct
+
+import "time"
+
+type SubMessage struct {
+ Id int
+ Description string
+ StartTime time.Time
+ EndTime *time.Time
+}
diff --git a/gojay/codegen/test/embedded_struct/encoding.go b/gojay/codegen/test/embedded_struct/encoding.go
@@ -0,0 +1,309 @@
+// Code generated by Gojay. DO NOT EDIT.
+
+package embedded_struct
+
+import (
+ "github.com/francoispqt/gojay"
+ "time"
+)
+
+type Ints []int
+
+// UnmarshalJSONArray decodes JSON array elements into slice
+func (a *Ints) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value int
+ if err := dec.Int(&value); err != nil {
+ return err
+ }
+ *a = append(*a, value)
+ return nil
+}
+
+// MarshalJSONArray encodes arrays into JSON
+func (a Ints) MarshalJSONArray(enc *gojay.Encoder) {
+ for _, item := range a {
+ enc.Int(item)
+ }
+}
+
+// IsNil checks if array is nil
+func (a Ints) IsNil() bool {
+ return len(a) == 0
+}
+
+type Float64s []float64
+
+// UnmarshalJSONArray decodes JSON array elements into slice
+func (a *Float64s) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value float64
+ if err := dec.Float64(&value); err != nil {
+ return err
+ }
+ *a = append(*a, value)
+ return nil
+}
+
+// MarshalJSONArray encodes arrays into JSON
+func (a Float64s) MarshalJSONArray(enc *gojay.Encoder) {
+ for _, item := range a {
+ enc.Float64(item)
+ }
+}
+
+// IsNil checks if array is nil
+func (a Float64s) IsNil() bool {
+ return len(a) == 0
+}
+
+type SubMessagesPtr []*SubMessage
+
+func (s *SubMessagesPtr) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value = &SubMessage{}
+ if err := dec.Object(value); err != nil {
+ return err
+ }
+ *s = append(*s, value)
+ return nil
+}
+
+func (s SubMessagesPtr) MarshalJSONArray(enc *gojay.Encoder) {
+ for i := range s {
+ enc.Object(s[i])
+ }
+}
+
+func (s SubMessagesPtr) IsNil() bool {
+ return len(s) == 0
+}
+
+type SubMessages []SubMessage
+
+func (s *SubMessages) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value = SubMessage{}
+ if err := dec.Object(&value); err != nil {
+ return err
+ }
+ *s = append(*s, value)
+ return nil
+}
+
+func (s SubMessages) MarshalJSONArray(enc *gojay.Encoder) {
+ for i := range s {
+ enc.Object(&s[i])
+ }
+}
+
+func (s SubMessages) IsNil() bool {
+ return len(s) == 0
+}
+
+// MarshalJSONObject implements MarshalerJSONObject
+func (m *SubMessage) MarshalJSONObject(enc *gojay.Encoder) {
+ enc.StringKey("Description", m.Description)
+ enc.TimeKey("StartTime", &m.StartTime, time.RFC3339)
+ if m.EndTime != nil {
+ enc.TimeKey("EndTime", m.EndTime, time.RFC3339)
+ }
+}
+
+// IsNil checks if instance is nil
+func (m *SubMessage) IsNil() bool {
+ return m == nil
+}
+
+// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
+func (m *SubMessage) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
+
+ switch k {
+ case "Description":
+ return dec.String(&m.Description)
+
+ case "StartTime":
+ var format = time.RFC3339
+ var value = time.Time{}
+ err := dec.Time(&value, format)
+ if err == nil {
+ m.StartTime = value
+ }
+ return err
+
+ case "EndTime":
+ var format = time.RFC3339
+ var value = &time.Time{}
+ err := dec.Time(value, format)
+ if err == nil {
+ m.EndTime = value
+ }
+ return err
+
+ }
+ return nil
+}
+
+// NKeys returns the number of keys to unmarshal
+func (m *SubMessage) NKeys() int { return 3 }
+
+// MarshalJSONObject implements MarshalerJSONObject
+func (m *Message) MarshalJSONObject(enc *gojay.Encoder) {
+ if m.BaseId != nil {
+ enc.IntKey("Id", m.Id)
+ enc.StringKey("Name", m.Name)
+ }
+ enc.StringKey("Description", m.Description)
+ enc.TimeKey("StartTime", &m.StartTime, time.RFC3339)
+ if m.EndTime != nil {
+ enc.TimeKey("EndTime", m.EndTime, time.RFC3339)
+ }
+ enc.Float64Key("Price", m.Price)
+ var intsSlice = Ints(m.Ints)
+ enc.ArrayKey("Ints", intsSlice)
+ var floatsSlice = Float64s(m.Floats)
+ enc.ArrayKey("Floats", floatsSlice)
+ enc.ObjectKey("SubMessageX", m.SubMessageX)
+ var messagesXSlice = SubMessagesPtr(m.MessagesX)
+ enc.ArrayKey("MessagesX", messagesXSlice)
+ enc.ObjectKey("SubMessageY", &m.SubMessageY)
+ var messagesYSlice = SubMessages(m.MessagesY)
+ enc.ArrayKey("MessagesY", messagesYSlice)
+ enc.BoolKey("IsTrue", *m.IsTrue)
+ var payloadSlice = gojay.EmbeddedJSON(m.Payload)
+ enc.AddEmbeddedJSONKey("Payload", &payloadSlice)
+}
+
+// IsNil checks if instance is nil
+func (m *Message) IsNil() bool {
+ return m == nil
+}
+
+// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
+func (m *Message) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
+ if m.BaseId == nil {
+ m.BaseId = &BaseId{}
+ }
+ switch k {
+ case "Id":
+ return dec.Int(&m.Id)
+
+ case "Name":
+ return dec.String(&m.Name)
+
+ case "Description":
+ return dec.String(&m.Description)
+
+ case "StartTime":
+ var format = time.RFC3339
+ var value = time.Time{}
+ err := dec.Time(&value, format)
+ if err == nil {
+ m.StartTime = value
+ }
+ return err
+
+ case "EndTime":
+ var format = time.RFC3339
+ var value = &time.Time{}
+ err := dec.Time(value, format)
+ if err == nil {
+ m.EndTime = value
+ }
+ return err
+
+ case "Price":
+ return dec.Float64(&m.Price)
+
+ case "Ints":
+ var aSlice = Ints{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.Ints = []int(aSlice)
+ }
+ return err
+
+ case "Floats":
+ var aSlice = Float64s{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.Floats = []float64(aSlice)
+ }
+ return err
+
+ case "SubMessageX":
+ var value = &SubMessage{}
+ err := dec.Object(value)
+ if err == nil {
+ m.SubMessageX = value
+ }
+
+ return err
+
+ case "MessagesX":
+ var aSlice = SubMessagesPtr{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.MessagesX = []*SubMessage(aSlice)
+ }
+ return err
+
+ case "SubMessageY":
+ err := dec.Object(&m.SubMessageY)
+
+ return err
+
+ case "MessagesY":
+ var aSlice = SubMessages{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.MessagesY = []SubMessage(aSlice)
+ }
+ return err
+
+ case "IsTrue":
+ var value bool
+ err := dec.Bool(&value)
+ if err == nil {
+ m.IsTrue = &value
+ }
+ return err
+
+ case "Payload":
+ var value = gojay.EmbeddedJSON{}
+ err := dec.AddEmbeddedJSON(&value)
+ if err == nil && len(value) > 0 {
+ m.Payload = []byte(value)
+ }
+ return err
+
+ }
+ return nil
+}
+
+// NKeys returns the number of keys to unmarshal
+func (m *Message) NKeys() int { return 14 }
+
+// MarshalJSONObject implements MarshalerJSONObject
+func (i *BaseId) MarshalJSONObject(enc *gojay.Encoder) {
+ enc.IntKey("Id", i.Id)
+ enc.StringKey("Name", i.Name)
+}
+
+// IsNil checks if instance is nil
+func (i *BaseId) IsNil() bool {
+ return i == nil
+}
+
+// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
+func (i *BaseId) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
+
+ switch k {
+ case "Id":
+ return dec.Int(&i.Id)
+
+ case "Name":
+ return dec.String(&i.Name)
+
+ }
+ return nil
+}
+
+// NKeys returns the number of keys to unmarshal
+func (i *BaseId) NKeys() int { return 2 }
diff --git a/gojay/codegen/test/embedded_struct/encoding_test.go b/gojay/codegen/test/embedded_struct/encoding_test.go
@@ -0,0 +1,106 @@
+package embedded_struct
+
+import (
+ "bytes"
+ "github.com/francoispqt/gojay"
+ "github.com/stretchr/testify/assert"
+ "github.com/viant/assertly"
+ "testing"
+)
+
+func TestMessage_Unmarshal(t *testing.T) {
+
+ input := `{
+ "Id": 1022,
+ "Name": "name acc",
+ "Description": "abcd",
+ "Price": 13.3,
+ "Ints": [
+ 1,
+ 2,
+ 5
+ ],
+ "Floats": [
+ 2.3,
+ 4.6,
+ 7.4
+ ],
+ "MessagesX": [
+ {
+ "Description": "abce"
+ }
+ ],
+ "SubMessageY": {
+ "Description": "abcf"
+ },
+ "MessagesY": [
+ {
+ "Description": "abcg"
+ },
+ {
+ "Description": "abcgg"
+ }
+ ],
+ "IsTrue": true,
+ "Payload": ""
+}`
+
+ var err error
+ var data = []byte(input)
+ message := &Message{}
+ err = gojay.UnmarshalJSONObject(data, message)
+ assert.Nil(t, err)
+ assertly.AssertValues(t, input, message)
+}
+
+func TestMessage_Marshal(t *testing.T) {
+
+ input := `{
+ "Id": 1022,
+ "Name": "name acc",
+ "Description": "abcd",
+ "Price": 13.3,
+ "Ints": [
+ 1,
+ 2,
+ 5
+ ],
+ "Floats": [
+ 2.3,
+ 4.6,
+ 7.4
+ ],
+ "MessagesX": [
+ {
+ "Description": "abce"
+ }
+ ],
+ "SubMessageY": {
+ "Description": "abcf"
+ },
+ "MessagesY": [
+ {
+ "Description": "abcg"
+ },
+ {
+ "Description": "abcgg"
+ }
+ ],
+ "IsTrue": true,
+ "Payload": ""
+}`
+
+ var err error
+ var data = []byte(input)
+ message := &Message{}
+ err = gojay.UnmarshalJSONObject(data, message)
+ assert.Nil(t, err)
+ assertly.AssertValues(t, input, message)
+ var writer = new(bytes.Buffer)
+
+ encoder := gojay.NewEncoder(writer)
+ err = encoder.Encode(message)
+ assert.Nil(t, err)
+ var JSON = writer.String()
+ assertly.AssertValues(t, input, JSON)
+}
diff --git a/gojay/codegen/test/embedded_struct/message.go b/gojay/codegen/test/embedded_struct/message.go
@@ -0,0 +1,20 @@
+package embedded_struct
+
+type BaseId struct {
+ Id int
+ Name string
+}
+
+type Message struct {
+ *BaseId
+ SubMessage
+ Price float64
+ Ints []int
+ Floats []float64
+ SubMessageX *SubMessage
+ MessagesX []*SubMessage
+ SubMessageY SubMessage
+ MessagesY []SubMessage
+ IsTrue *bool
+ Payload []byte
+}
diff --git a/gojay/codegen/test/embedded_struct/sub_message.go b/gojay/codegen/test/embedded_struct/sub_message.go
@@ -0,0 +1,9 @@
+package embedded_struct
+
+import "time"
+
+type SubMessage struct {
+ Description string
+ StartTime time.Time
+ EndTime *time.Time
+}
diff --git a/gojay/codegen/test/pooled_struct/encoding.go b/gojay/codegen/test/pooled_struct/encoding.go
@@ -0,0 +1,302 @@
+// Code generated by Gojay. DO NOT EDIT.
+
+package pooled_struct
+
+import (
+ "github.com/francoispqt/gojay"
+ "sync"
+ "time"
+)
+
+func init() {
+ MessagePool = &sync.Pool{
+ New: func() interface{} {
+ return &Message{}
+ },
+ }
+ SubMessagePool = &sync.Pool{
+ New: func() interface{} {
+ return &SubMessage{}
+ },
+ }
+}
+
+var MessagePool *sync.Pool
+var SubMessagePool *sync.Pool
+
+type Ints []int
+
+// UnmarshalJSONArray decodes JSON array elements into slice
+func (a *Ints) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value int
+ if err := dec.Int(&value); err != nil {
+ return err
+ }
+ *a = append(*a, value)
+ return nil
+}
+
+// MarshalJSONArray encodes arrays into JSON
+func (a Ints) MarshalJSONArray(enc *gojay.Encoder) {
+ for _, item := range a {
+ enc.Int(item)
+ }
+}
+
+// IsNil checks if array is nil
+func (a Ints) IsNil() bool {
+ return len(a) == 0
+}
+
+type Float64s []float64
+
+// UnmarshalJSONArray decodes JSON array elements into slice
+func (a *Float64s) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value float64
+ if err := dec.Float64(&value); err != nil {
+ return err
+ }
+ *a = append(*a, value)
+ return nil
+}
+
+// MarshalJSONArray encodes arrays into JSON
+func (a Float64s) MarshalJSONArray(enc *gojay.Encoder) {
+ for _, item := range a {
+ enc.Float64(item)
+ }
+}
+
+// IsNil checks if array is nil
+func (a Float64s) IsNil() bool {
+ return len(a) == 0
+}
+
+type SubMessagesPtr []*SubMessage
+
+func (s *SubMessagesPtr) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value = &SubMessage{}
+ if err := dec.Object(value); err != nil {
+ return err
+ }
+ *s = append(*s, value)
+ return nil
+}
+
+func (s SubMessagesPtr) MarshalJSONArray(enc *gojay.Encoder) {
+ for i := range s {
+ enc.Object(s[i])
+ }
+}
+
+func (s SubMessagesPtr) IsNil() bool {
+ return len(s) == 0
+}
+
+type SubMessages []SubMessage
+
+func (s *SubMessages) UnmarshalJSONArray(dec *gojay.Decoder) error {
+ var value = SubMessage{}
+ if err := dec.Object(&value); err != nil {
+ return err
+ }
+ *s = append(*s, value)
+ return nil
+}
+
+func (s SubMessages) MarshalJSONArray(enc *gojay.Encoder) {
+ for i := range s {
+ enc.Object(&s[i])
+ }
+}
+
+func (s SubMessages) IsNil() bool {
+ return len(s) == 0
+}
+
+// MarshalJSONObject implements MarshalerJSONObject
+func (m *SubMessage) MarshalJSONObject(enc *gojay.Encoder) {
+ enc.IntKey("Id", m.Id)
+ enc.StringKey("Description", m.Description)
+ enc.TimeKey("StartTime", &m.StartTime, time.RFC3339)
+ if m.EndTime != nil {
+ enc.TimeKey("EndTime", m.EndTime, time.RFC3339)
+ }
+}
+
+// IsNil checks if instance is nil
+func (m *SubMessage) IsNil() bool {
+ return m == nil
+}
+
+// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
+func (m *SubMessage) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
+
+ switch k {
+ case "Id":
+ return dec.Int(&m.Id)
+
+ case "Description":
+ return dec.String(&m.Description)
+
+ case "StartTime":
+ var format = time.RFC3339
+ var value = time.Time{}
+ err := dec.Time(&value, format)
+ if err == nil {
+ m.StartTime = value
+ }
+ return err
+
+ case "EndTime":
+ var format = time.RFC3339
+ var value = &time.Time{}
+ err := dec.Time(value, format)
+ if err == nil {
+ m.EndTime = value
+ }
+ return err
+
+ }
+ return nil
+}
+
+// NKeys returns the number of keys to unmarshal
+func (m *SubMessage) NKeys() int { return 4 }
+
+// Reset reset fields
+func (m *SubMessage) Reset() {
+ m.Id = 0
+ m.Description = ""
+ m.EndTime = nil
+}
+
+// MarshalJSONObject implements MarshalerJSONObject
+func (m *Message) MarshalJSONObject(enc *gojay.Encoder) {
+ enc.IntKey("Id", m.Id)
+ enc.StringKey("Name", m.Name)
+ enc.Float64Key("Price", m.Price)
+ var intsSlice = Ints(m.Ints)
+ enc.ArrayKey("Ints", intsSlice)
+ var floatsSlice = Float64s(m.Floats)
+ enc.ArrayKey("Floats", floatsSlice)
+ enc.ObjectKey("SubMessageX", m.SubMessageX)
+ var messagesXSlice = SubMessagesPtr(m.MessagesX)
+ enc.ArrayKey("MessagesX", messagesXSlice)
+ enc.ObjectKey("SubMessageY", &m.SubMessageY)
+ var messagesYSlice = SubMessages(m.MessagesY)
+ enc.ArrayKey("MessagesY", messagesYSlice)
+ enc.BoolKey("IsTrue", *m.IsTrue)
+ var payloadSlice = gojay.EmbeddedJSON(m.Payload)
+ enc.AddEmbeddedJSONKey("Payload", &payloadSlice)
+}
+
+// IsNil checks if instance is nil
+func (m *Message) IsNil() bool {
+ return m == nil
+}
+
+// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
+func (m *Message) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
+
+ switch k {
+ case "Id":
+ return dec.Int(&m.Id)
+
+ case "Name":
+ return dec.String(&m.Name)
+
+ case "Price":
+ return dec.Float64(&m.Price)
+
+ case "Ints":
+ var aSlice = Ints{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.Ints = []int(aSlice)
+ }
+ return err
+
+ case "Floats":
+ var aSlice = Float64s{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.Floats = []float64(aSlice)
+ }
+ return err
+
+ case "SubMessageX":
+ var value = SubMessagePool.Get().(*SubMessage)
+ err := dec.Object(value)
+ if err == nil {
+ m.SubMessageX = value
+ }
+
+ return err
+
+ case "MessagesX":
+ var aSlice = SubMessagesPtr{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.MessagesX = []*SubMessage(aSlice)
+ }
+ return err
+
+ case "SubMessageY":
+ err := dec.Object(&m.SubMessageY)
+
+ return err
+
+ case "MessagesY":
+ var aSlice = SubMessages{}
+ err := dec.Array(&aSlice)
+ if err == nil && len(aSlice) > 0 {
+ m.MessagesY = []SubMessage(aSlice)
+ }
+ return err
+
+ case "IsTrue":
+ var value bool
+ err := dec.Bool(&value)
+ if err == nil {
+ m.IsTrue = &value
+ }
+ return err
+
+ case "Payload":
+ var value = gojay.EmbeddedJSON{}
+ err := dec.AddEmbeddedJSON(&value)
+ if err == nil && len(value) > 0 {
+ m.Payload = []byte(value)
+ }
+ return err
+
+ }
+ return nil
+}
+
+// NKeys returns the number of keys to unmarshal
+func (m *Message) NKeys() int { return 11 }
+
+// Reset reset fields
+func (m *Message) Reset() {
+ m.Id = 0
+ m.Name = ""
+ m.Price = 0.0
+ m.Ints = nil
+ m.Floats = nil
+ SubMessagePool.Put(m.SubMessageX)
+ m.SubMessageX = nil
+ for i := range m.MessagesX {
+ m.MessagesX[i].Reset()
+ SubMessagePool.Put(m.MessagesX[i])
+ }
+ m.MessagesX = nil
+ for i := range m.MessagesY {
+ m.MessagesY[i].Reset()
+ SubMessagePool.Put(&m.MessagesY[i])
+ }
+ m.MessagesY = nil
+ m.IsTrue = nil
+ m.Payload = nil
+}
diff --git a/gojay/codegen/test/pooled_struct/encoding_test.go b/gojay/codegen/test/pooled_struct/encoding_test.go
@@ -0,0 +1,123 @@
+package pooled_struct
+
+import (
+ "bytes"
+ "github.com/francoispqt/gojay"
+ "github.com/stretchr/testify/assert"
+ "github.com/viant/assertly"
+ "testing"
+)
+
+func TestMessage_Unmarshal(t *testing.T) {
+
+ input := `{
+ "Id": 1022,
+ "Name": "name acc",
+ "Price": 13.3,
+ "Ints": [
+ 1,
+ 2,
+ 5
+ ],
+ "Floats": [
+ 2.3,
+ 4.6,
+ 7.4
+ ],
+ "SubMessageX": {
+ "Id": 102,
+ "Description": "abcd"
+ },
+ "MessagesX": [
+ {
+ "Id": 2102,
+ "Description": "abce"
+ }
+ ],
+ "SubMessageY": {
+ "Id": 3102,
+ "Description": "abcf"
+ },
+ "MessagesY": [
+ {
+ "Id": 5102,
+ "Description": "abcg"
+ },
+ {
+ "Id": 5106,
+ "Description": "abcgg"
+ }
+ ],
+ "IsTrue": true,
+ "Payload": ""
+}`
+
+ var data = []byte(input)
+ message := MessagePool.Get().(*Message)
+ err := gojay.UnmarshalJSONObject(data, message)
+ assert.Nil(t, err)
+ message.Reset()
+ MessagePool.Put(message)
+
+}
+
+func TestMessage_Marshal(t *testing.T) {
+
+ input := `{
+ "Id": 1022,
+ "Name": "name acc",
+ "Price": 13.3,
+ "Ints": [
+ 1,
+ 2,
+ 5
+ ],
+ "Floats": [
+ 2.3,
+ 4.6,
+ 7.4
+ ],
+ "SubMessageX": {
+ "Id": 102,
+ "Description": "abcd"
+ },
+ "MessagesX": [
+ {
+ "Id": 2102,
+ "Description": "abce"
+ }
+ ],
+ "SubMessageY": {
+ "Id": 3102,
+ "Description": "abcf"
+ },
+ "MessagesY": [
+ {
+ "Id": 5102,
+ "Description": "abcg"
+ },
+ {
+ "Id": 5106,
+ "Description": "abcgg"
+ }
+ ],
+ "IsTrue": true,
+ "Payload": ""
+}`
+
+ var data = []byte(input)
+ message := MessagePool.Get().(*Message)
+ err := gojay.UnmarshalJSONObject(data, message)
+ assert.Nil(t, err)
+ defer func() {
+ message.Reset()
+ MessagePool.Put(message)
+
+ }()
+ var writer = new(bytes.Buffer)
+ encoder := gojay.NewEncoder(writer)
+ err = encoder.Encode(message)
+ assert.Nil(t, err)
+ var JSON = writer.String()
+ assertly.AssertValues(t, input, JSON)
+}
diff --git a/gojay/codegen/test/pooled_struct/message.go b/gojay/codegen/test/pooled_struct/message.go
@@ -0,0 +1,15 @@
+package pooled_struct
+
+type Message struct {
+ Id int
+ Name string
+ Price float64
+ Ints []int
+ Floats []float64
+ SubMessageX *SubMessage
+ MessagesX []*SubMessage
+ SubMessageY SubMessage
+ MessagesY []SubMessage
+ IsTrue *bool
+ Payload []byte
+}
diff --git a/gojay/codegen/test/pooled_struct/sub_message.go b/gojay/codegen/test/pooled_struct/sub_message.go
@@ -0,0 +1,10 @@
+package pooled_struct
+
+import "time"
+
+type SubMessage struct {
+ Id int
+ Description string
+ StartTime time.Time
+ EndTime *time.Time
+}
diff --git a/gojay/gen.go b/gojay/gen.go
@@ -1,146 +0,0 @@
-package main
-
-import (
- "go/ast"
- "log"
- "strings"
- "text/template"
-)
-
-const gojayAnnotation = "//gojay:json"
-const genFileSuffix = "_gojay.go"
-const omitEmptyFuncName = "OmitEmpty"
-
-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
-}
-
-type genTpl struct {
- strTpl string
- tpl *template.Template
-}
-
-type templateList map[string]*genTpl
-
-func init() {
- t, err := template.New("pkgDef").
- Parse("package {{.PkgName}} \n\n")
- if err != nil {
- log.Fatal(err)
- }
- pkgTpl = t
-}
-
-func parseTemplates(tpls templateList, pfx string) {
- for k, t := range tpls {
- tpl, err := template.New(pfx + k).Parse(t.strTpl)
- if err != nil {
- log.Fatal(err)
- }
- t.tpl = tpl
- }
-}
-
-// NewGen returns a new generator
-func NewGen(p string, types []string) *Gen {
- g := &Gen{
- src: p,
- types: types,
- b: &strings.Builder{},
- genTypes: make(map[string]*ast.TypeSpec),
- }
- return g
-}
-
-func (g *Gen) writePkg(pkg string) error {
- err := pkgTpl.Execute(g.b, struct {
- PkgName string
- }{
- PkgName: pkg,
- })
- if err != nil {
- return err
- }
- return nil
-}
-
-func (g *Gen) writeGojayImport() error {
- _, err := g.b.Write(gojayImport)
- if err != nil {
- return err
- }
- 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)
- if err != nil {
- return err
- }
- // write import of gojay
- err = g.writeGojayImport()
- if err != nil {
- return err
- }
- // range over specs
- // generate interfaces implementations based on type
- for _, s := range g.genTypes {
- switch t := s.Type.(type) {
- // is struct
- case *ast.StructType:
- err = g.genStruct(s.Name.String(), t)
- if err != nil {
- return err
- }
- // is array
- case *ast.ArrayType:
- err = g.genArray(s.Name.String(), t)
- if err != nil {
- return err
- }
- // is map
- case *ast.MapType:
- // TODO: generate for map type
- err = g.genMap(s.Name.String(), t)
- if err != nil {
- return err
- }
- }
- }
- return nil
-}
diff --git a/gojay/gen_array.go b/gojay/gen_array.go
@@ -1,17 +0,0 @@
-package main
-
-import (
- "go/ast"
-)
-
-func (g *Gen) genArray(n string, s *ast.ArrayType) error {
- err := g.arrGenUnmarshal(n, s)
- if err != nil {
- return err
- }
- err = g.arrGenMarshal(n, s)
- if err != nil {
- return err
- }
- return g.arrGenIsNil(n)
-}
diff --git a/gojay/gen_array_marshal.go b/gojay/gen_array_marshal.go
@@ -1,241 +0,0 @@
-package main
-
-import (
- "errors"
- "fmt"
- "go/ast"
- "log"
-)
-
-func init() {}
-
-func (g *Gen) arrGenIsNil(n string) error {
- err := arrMarshalTpl["isNil"].tpl.Execute(g.b, struct {
- TypeName string
- }{
- TypeName: n,
- })
- return err
-}
-
-func (g *Gen) arrGenMarshal(n string, s *ast.ArrayType) error {
- err := arrMarshalTpl["def"].tpl.Execute(g.b, struct {
- TypeName string
- }{
- TypeName: n,
- })
- if err != nil {
- return err
- }
- // determine type of element in array
- switch t := s.Elt.(type) {
- case *ast.Ident:
- err := g.arrGenMarshalIdent(t, false)
- if err != nil {
- return err
- }
- case *ast.StarExpr:
- switch ptrExp := t.X.(type) {
- case *ast.Ident:
- err := g.arrGenMarshalIdent(ptrExp, true)
- if err != nil {
- return err
- }
- default:
- return fmt.Errorf("Unknown type %s", n)
- }
- }
- _, err = g.b.Write([]byte("}\n"))
- if err != nil {
- return err
- }
- return err
-}
-
-func (g *Gen) arrGenMarshalIdent(i *ast.Ident, ptr bool) error {
- switch i.String() {
- case "string":
- g.arrMarshalString(ptr)
- case "bool":
- g.arrMarshalBool(ptr)
- case "int":
- g.arrMarshalInt("", ptr)
- case "int64":
- g.arrMarshalInt("64", ptr)
- case "int32":
- g.arrMarshalInt("32", ptr)
- case "int16":
- g.arrMarshalInt("16", ptr)
- case "int8":
- g.arrMarshalInt("8", ptr)
- case "uint64":
- g.arrMarshalUint("64", ptr)
- case "uint32":
- g.arrMarshalUint("32", ptr)
- case "uint16":
- g.arrMarshalUint("16", ptr)
- case "uint8":
- g.arrMarshalUint("8", ptr)
- case "float64":
- g.arrMarshalFloat("64", ptr)
- case "float32":
- g.arrMarshalFloat("32", ptr)
- default:
- // if ident is already in our spec list
- if sp, ok := g.genTypes[i.Name]; ok {
- return g.arrMarshalNonPrim(sp, ptr)
- } else if i.Obj != nil {
- // else check the obj infos
- switch t := i.Obj.Decl.(type) {
- case *ast.TypeSpec:
- return g.arrMarshalNonPrim(t, ptr)
- default:
- return errors.New("could not determine what to do with type " + i.String())
- }
- }
- return fmt.Errorf("Unknown type %s", i.Name)
- }
- return nil
-}
-
-func (g *Gen) arrMarshalNonPrim(sp *ast.TypeSpec, ptr bool) error {
- switch sp.Type.(type) {
- case *ast.StructType:
- g.arrMarshalStruct(sp, ptr)
- case *ast.ArrayType:
- g.arrMarshalArr(sp, ptr)
- }
- return nil
-}
-
-func (g *Gen) arrMarshalString(ptr bool) {
- if ptr {
- err := arrMarshalTpl["stringPtr"].tpl.Execute(g.b, struct {
- Ptr string
- }{""})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := arrMarshalTpl["string"].tpl.Execute(g.b, struct {
- Ptr string
- }{"&"})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-func (g *Gen) arrMarshalBool(ptr bool) {
- if ptr {
- err := arrMarshalTpl["bool"].tpl.Execute(g.b, struct {
- Ptr string
- }{""})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := arrMarshalTpl["bool"].tpl.Execute(g.b, struct {
- Ptr string
- }{"&"})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-func (g *Gen) arrMarshalInt(intLen string, ptr bool) {
- if ptr {
- err := arrMarshalTpl["int"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, ""})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := arrMarshalTpl["int"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, "&"})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-func (g *Gen) arrMarshalFloat(intLen string, ptr bool) {
- if ptr {
- err := arrMarshalTpl["float"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, ""})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := arrMarshalTpl["float"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, "&"})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-func (g *Gen) arrMarshalUint(intLen string, ptr bool) {
- if ptr {
- err := arrMarshalTpl["uint"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, ""})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := arrMarshalTpl["uint"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, "&"})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-func (g *Gen) arrMarshalStruct(st *ast.TypeSpec, ptr bool) {
- if ptr {
- err := arrMarshalTpl["structPtr"].tpl.Execute(g.b, struct {
- StructName string
- }{st.Name.String()})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := arrMarshalTpl["struct"].tpl.Execute(g.b, struct {
- StructName string
- }{st.Name.String()})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-func (g *Gen) arrMarshalArr(st *ast.TypeSpec, ptr bool) {
- if ptr {
- err := arrMarshalTpl["arrPtr"].tpl.Execute(g.b, struct {
- StructName string
- }{st.Name.String()})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := arrMarshalTpl["arr"].tpl.Execute(g.b, struct {
- StructName string
- }{st.Name.String()})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
diff --git a/gojay/gen_array_marshal_tpl.go b/gojay/gen_array_marshal_tpl.go
@@ -1,63 +0,0 @@
-package main
-
-var arrMarshalTpl = templateList{
- "def": &genTpl{
- strTpl: "\n// MarshalJSONArray implements gojay's MarshalerJSONArray" +
- "\nfunc (v *{{.TypeName}}) MarshalJSONArray(enc *gojay.Encoder) {\n",
- },
- "isNil": &genTpl{
- strTpl: "\n// IsNil implements gojay's MarshalerJSONArray" +
- "\nfunc (v *{{.TypeName}}) IsNil() bool {\n" +
- "\treturn *v == nil || len(*v) == 0\n" +
- "}\n",
- },
- "string": &genTpl{
- strTpl: "\tfor _, s := range *v {\n" +
- "\t\tenc.String(s)\n" +
- "\t}\n",
- },
- "bool": &genTpl{
- strTpl: "\tfor _, s := range *v {\n" +
- "\t\tenc.Bool(s)\n" +
- "\t}\n",
- },
- "int": &genTpl{
- strTpl: "\tfor _, s := range *v {\n" +
- "\t\tenc.Int{{.IntLen}}(s)\n" +
- "\t}\n",
- },
- "uint": &genTpl{
- strTpl: "\tfor _, s := range *v {\n" +
- "\t\tenc.Uint{{.IntLen}}(s)\n" +
- "\t}\n",
- },
- "float": &genTpl{
- strTpl: "\tfor _, s := range *v {\n" +
- "\t\tenc.Float{{.IntLen}}(s)\n" +
- "\t}\n",
- },
- "struct": &genTpl{
- strTpl: "\tfor _, s := range *v {\n" +
- "\t\tenc.Object(s)\n" +
- "\t}\n",
- },
- "structPtr": &genTpl{
- strTpl: "\tfor _, s := range *v {\n" +
- "\t\tenc.Object(s)\n" +
- "\t}\n",
- },
- "arr": &genTpl{
- strTpl: "\tfor _, s := range *v {\n" +
- "\t\tenc.Array(s)\n" +
- "\t}\n",
- },
- "arrPtr": &genTpl{
- strTpl: "\tfor _, s := range *v {\n" +
- "\t\tenc.Array(s)\n" +
- "\t}\n",
- },
-}
-
-func init() {
- parseTemplates(arrMarshalTpl, "arrMarshal")
-}
diff --git a/gojay/gen_array_test.go b/gojay/gen_array_test.go
@@ -1,436 +0,0 @@
-package main
-
-import (
- "io"
- "strings"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestGenArray(t *testing.T) {
- testCases := map[string]struct {
- input io.Reader
- expectedResult string
- }{
- "basicStringSlice": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type StrSlice []string
- `),
- expectedResult: `package
-
-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
-}
-`,
- },
- "basicStringBool": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type BoolSlice []bool
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// 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
-}
-`,
- },
- "basicIntSlice": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type IntSlice []int
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// 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
-}
-`,
- },
- "basicInt8Slice": {
- input: strings.NewReader(`package test
-
- //gojay:json
- type IntSlice []int8
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray
-func (v *IntSlice) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var i int8
- if err := dec.Int8(&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.Int8(s)
- }
-}
-
-// IsNil implements gojay's MarshalerJSONArray
-func (v *IntSlice) IsNil() bool {
- return *v == nil || len(*v) == 0
-}
-`,
- },
- "basicInt16Slice": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type IntSlice []int16
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray
-func (v *IntSlice) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var i int16
- if err := dec.Int16(&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.Int16(s)
- }
-}
-
-// IsNil implements gojay's MarshalerJSONArray
-func (v *IntSlice) IsNil() bool {
- return *v == nil || len(*v) == 0
-}
-`,
- },
- "basicInt32Slice": {
- input: strings.NewReader(`package test
-
- //gojay:json
- type IntSlice []int32
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray
-func (v *IntSlice) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var i int32
- if err := dec.Int32(&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.Int32(s)
- }
-}
-
-// IsNil implements gojay's MarshalerJSONArray
-func (v *IntSlice) IsNil() bool {
- return *v == nil || len(*v) == 0
-}
-`,
- },
- "basicInt64Slice": {
- input: strings.NewReader(`package test
-
- //gojay:json
- type IntSlice []int64
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray
-func (v *IntSlice) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var i int64
- if err := dec.Int64(&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.Int64(s)
- }
-}
-
-// IsNil implements gojay's MarshalerJSONArray
-func (v *IntSlice) IsNil() bool {
- return *v == nil || len(*v) == 0
-}
-`,
- },
- "basicUint64Slice": {
- input: strings.NewReader(`package test
-
- //gojay:json
- type IntSlice []uint64
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray
-func (v *IntSlice) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var i uint64
- if err := dec.Uint64(&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.Uint64(s)
- }
-}
-
-// IsNil implements gojay's MarshalerJSONArray
-func (v *IntSlice) IsNil() bool {
- return *v == nil || len(*v) == 0
-}
-`,
- },
- "basicFloatSlice": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type IntSlice []float64
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray
-func (v *IntSlice) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var i float64
- if err := dec.Float64(&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.Float64(s)
- }
-}
-
-// IsNil implements gojay's MarshalerJSONArray
-func (v *IntSlice) IsNil() bool {
- return *v == nil || len(*v) == 0
-}
-`,
- },
- "basicFloat32Slice": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type IntSlice []float32
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray
-func (v *IntSlice) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var i float32
- if err := dec.Float32(&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.Float32(s)
- }
-}
-
-// IsNil implements gojay's MarshalerJSONArray
-func (v *IntSlice) IsNil() bool {
- return *v == nil || len(*v) == 0
-}
-`,
- },
- "basicStructSlice": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type StructSlice []*Struct
-
-type Struct struct{
- Str string
-}
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray
-func (v *StructSlice) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var s = &Struct{}
- 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
-}
-`,
- },
- "basicSliceSlice": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type SliceStrSlice []StrSlice
-
-type StrSlice []string
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray
-func (v *SliceStrSlice) 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 *SliceStrSlice) MarshalJSONArray(enc *gojay.Encoder) {
- for _, s := range *v {
- enc.Array(s)
- }
-}
-
-// IsNil implements gojay's MarshalerJSONArray
-func (v *SliceStrSlice) IsNil() bool {
- return *v == nil || len(*v) == 0
-}
-`,
- },
- }
- for n, testCase := range testCases {
- t.Run(n, func(t *testing.T) {
- g, err := MakeGenFromReader(testCase.input)
- if err != nil {
- t.Fatal(err)
- }
- err = g.Gen()
- if err != nil {
- t.Fatal(err)
- }
- assert.Equal(
- t,
- string(genHeader)+testCase.expectedResult,
- g.b.String(),
- )
- })
- }
-}
diff --git a/gojay/gen_array_unmarshal.go b/gojay/gen_array_unmarshal.go
@@ -1,230 +0,0 @@
-package main
-
-import (
- "errors"
- "fmt"
- "go/ast"
- "log"
-)
-
-func (g *Gen) arrGenUnmarshal(n string, s *ast.ArrayType) error {
- err := arrUnmarshalTpl["def"].tpl.Execute(g.b, struct {
- TypeName string
- }{
- TypeName: n,
- })
- if err != nil {
- return err
- }
- // determine type of element in array
- switch t := s.Elt.(type) {
- case *ast.Ident:
- err := g.arrGenUnmarshalIdent(t, false)
- if err != nil {
- return err
- }
- case *ast.StarExpr:
- switch ptrExp := t.X.(type) {
- case *ast.Ident:
- err := g.arrGenUnmarshalIdent(ptrExp, true)
- if err != nil {
- return err
- }
- default:
- return fmt.Errorf("Unknown type %s", n)
- }
- }
- _, err = g.b.Write(structUnmarshalClose)
- if err != nil {
- return err
- }
- return err
-}
-
-func (g *Gen) arrGenUnmarshalIdent(i *ast.Ident, ptr bool) error {
- switch i.String() {
- case "string":
- g.arrUnmarshalString(ptr)
- case "bool":
- g.arrUnmarshalBool(ptr)
- case "int":
- g.arrUnmarshalInt("", ptr)
- case "int64":
- g.arrUnmarshalInt("64", ptr)
- case "int32":
- g.arrUnmarshalInt("32", ptr)
- case "int16":
- g.arrUnmarshalInt("16", ptr)
- case "int8":
- g.arrUnmarshalInt("8", ptr)
- case "uint64":
- g.arrUnmarshalUint("64", ptr)
- case "uint32":
- g.arrUnmarshalUint("32", ptr)
- case "uint16":
- g.arrUnmarshalUint("16", ptr)
- case "uint8":
- g.arrUnmarshalUint("8", ptr)
- case "float64":
- g.arrUnmarshalFloat("64", ptr)
- case "float32":
- g.arrUnmarshalFloat("32", ptr)
- default:
- // if ident is already in our spec list
- if sp, ok := g.genTypes[i.Name]; ok {
- return g.arrUnmarshalNonPrim(sp, ptr)
- } else if i.Obj != nil {
- // else check the obj infos
- switch t := i.Obj.Decl.(type) {
- case *ast.TypeSpec:
- return g.arrUnmarshalNonPrim(t, ptr)
- default:
- return errors.New("could not determine what to do with type " + i.String())
- }
- }
- return fmt.Errorf("Unknown type %s", i.Name)
- }
- return nil
-}
-
-func (g *Gen) arrUnmarshalNonPrim(sp *ast.TypeSpec, ptr bool) error {
- switch sp.Type.(type) {
- case *ast.StructType:
- g.arrUnmarshalStruct(sp, ptr)
- case *ast.ArrayType:
- g.arrUnmarshalArr(sp, ptr)
- }
- return nil
-}
-
-func (g *Gen) arrUnmarshalString(ptr bool) {
- if ptr {
- err := arrUnmarshalTpl["stringPtr"].tpl.Execute(g.b, struct {
- Ptr string
- }{""})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := arrUnmarshalTpl["string"].tpl.Execute(g.b, struct {
- Ptr string
- }{"&"})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-func (g *Gen) arrUnmarshalBool(ptr bool) {
- if ptr {
- err := arrUnmarshalTpl["bool"].tpl.Execute(g.b, struct {
- Ptr string
- }{""})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := arrUnmarshalTpl["bool"].tpl.Execute(g.b, struct {
- Ptr string
- }{"&"})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-func (g *Gen) arrUnmarshalInt(intLen string, ptr bool) {
- if ptr {
- err := arrUnmarshalTpl["int"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, ""})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := arrUnmarshalTpl["int"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, "&"})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-func (g *Gen) arrUnmarshalUint(intLen string, ptr bool) {
- if ptr {
- err := arrUnmarshalTpl["uint"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, ""})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := arrUnmarshalTpl["uint"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, "&"})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-func (g *Gen) arrUnmarshalFloat(intLen string, ptr bool) {
- if ptr {
- err := arrUnmarshalTpl["float"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, ""})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := arrUnmarshalTpl["float"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, "&"})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-func (g *Gen) arrUnmarshalStruct(st *ast.TypeSpec, ptr bool) {
- if ptr {
- err := arrUnmarshalTpl["structPtr"].tpl.Execute(g.b, struct {
- StructName string
- }{st.Name.String()})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := arrUnmarshalTpl["struct"].tpl.Execute(g.b, struct {
- StructName string
- }{st.Name.String()})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-func (g *Gen) arrUnmarshalArr(st *ast.TypeSpec, ptr bool) {
- if ptr {
- err := arrUnmarshalTpl["arrPtr"].tpl.Execute(g.b, struct {
- StructName string
- }{st.Name.String()})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := arrUnmarshalTpl["arr"].tpl.Execute(g.b, struct {
- StructName string
- }{st.Name.String()})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
diff --git a/gojay/gen_array_unmarshal_tpl.go b/gojay/gen_array_unmarshal_tpl.go
@@ -1,70 +0,0 @@
-package main
-
-var arrUnmarshalTpl = templateList{
- "def": &genTpl{
- strTpl: "\n// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray" +
- "\nfunc (v *{{.TypeName}}) UnmarshalJSONArray(dec *gojay.Decoder) error {\n",
- },
- "string": &genTpl{
- strTpl: "\tvar str string" +
- "\n\tif err := dec.String(&str); err != nil {\n" +
- "\t\treturn err\n\t}\n" +
- "\t*v = append(*v, str)\n",
- },
- "stringPtr": &genTpl{
- strTpl: "\n// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray" +
- "\nfunc (v *{{.TypeName}}) UnmarshalJSONArray(dec *gojay.Decoder) error {\n",
- },
- "int": &genTpl{
- strTpl: "\tvar i int{{.IntLen}}" +
- "\n\tif err := dec.Int{{.IntLen}}(&i); err != nil {\n" +
- "\t\treturn err\n\t}\n" +
- "\t*v = append(*v, i)\n",
- },
- "uint": &genTpl{
- strTpl: "\tvar i uint{{.IntLen}}" +
- "\n\tif err := dec.Uint{{.IntLen}}(&i); err != nil {\n" +
- "\t\treturn err\n\t}\n" +
- "\t*v = append(*v, i)\n",
- },
- "float": &genTpl{
- strTpl: "\tvar i float{{.IntLen}}" +
- "\n\tif err := dec.Float{{.IntLen}}(&i); err != nil {\n" +
- "\t\treturn err\n\t}\n" +
- "\t*v = append(*v, i)\n",
- },
- "bool": &genTpl{
- strTpl: "\tvar b bool" +
- "\n\tif err := dec.Bool(&b); err != nil {\n" +
- "\t\treturn err\n\t}\n" +
- "\t*v = append(*v, b)\n",
- },
- "struct": &genTpl{
- strTpl: "\tvar s = {{.StructName}}{}" +
- "\n\tif err := dec.Object(&s); err != nil {\n" +
- "\t\treturn err\n\t}\n" +
- "\t*v = append(*v, s)\n",
- },
- "structPtr": &genTpl{
- strTpl: "\tvar s = &{{.StructName}}{}" +
- "\n\tif err := dec.Object(s); err != nil {\n" +
- "\t\treturn err\n\t}\n" +
- "\t*v = append(*v, s)\n",
- },
- "arr": &genTpl{
- strTpl: "\tvar s = make({{.StructName}}, 0)" +
- "\n\tif err := dec.Array(&s); err != nil {\n" +
- "\t\treturn err\n\t}\n" +
- "\t*v = append(*v, s)\n",
- },
- "arrPtr": &genTpl{
- strTpl: "\tvar s = make({{.StructName}}, 0)" +
- "\n\tif err := dec.Array(&s); err != nil {\n" +
- "\t\treturn err\n\t}\n" +
- "\t*v = append(*v, &s)\n",
- },
-}
-
-func init() {
- parseTemplates(arrUnmarshalTpl, "arrUnmarshal")
-}
diff --git a/gojay/gen_map.go b/gojay/gen_map.go
@@ -1,19 +0,0 @@
-package main
-
-import "go/ast"
-
-func (g *Gen) genMap(n string, s *ast.MapType) error {
- err := g.mapGenUnmarshalObj(n, s)
- if err != nil {
- return err
- }
- err = g.mapGenNKeys(n, 0)
- if err != nil {
- return err
- }
- err = g.mapGenMarshalObj(n, s)
- if err != nil {
- return err
- }
- return g.mapGenIsNil(n)
-}
diff --git a/gojay/gen_map_marshal.go b/gojay/gen_map_marshal.go
@@ -1,201 +0,0 @@
-package main
-
-import (
- "errors"
- "fmt"
- "go/ast"
- "log"
-)
-
-func (g *Gen) mapGenIsNil(n string) error {
- err := mapMarshalTpl["isNil"].tpl.Execute(g.b, struct {
- StructName string
- }{
- StructName: n,
- })
- return err
-}
-
-func (g *Gen) mapGenMarshalObj(n string, s *ast.MapType) error {
- err := mapMarshalTpl["def"].tpl.Execute(g.b, struct {
- StructName string
- }{
- StructName: n,
- })
- if err != nil {
- return err
- }
- switch t := s.Value.(type) {
- case *ast.Ident:
- var err error
- err = g.mapGenMarshalIdent(t, false)
- if err != nil {
- return err
- }
- case *ast.StarExpr:
- switch ptrExp := t.X.(type) {
- case *ast.Ident:
- var err error
- err = g.mapGenMarshalIdent(ptrExp, true)
- if err != nil {
- return err
- }
- default:
- return fmt.Errorf("Unknown type %s", n)
- }
- }
- _, err = g.b.Write([]byte("}\n"))
- if err != nil {
- return err
- }
- return nil
-}
-
-func (g *Gen) mapGenMarshalIdent(i *ast.Ident, ptr bool) error {
- switch i.String() {
- case "string":
- g.mapMarshalString(ptr)
- case "bool":
- g.mapMarshalBool(ptr)
- case "int":
- g.mapMarshalInt("", ptr)
- case "int64":
- g.mapMarshalInt("64", ptr)
- case "int32":
- g.mapMarshalInt("32", ptr)
- case "int16":
- g.mapMarshalInt("16", ptr)
- case "int8":
- g.mapMarshalInt("8", ptr)
- case "uint64":
- g.mapMarshalUint("64", ptr)
- case "uint32":
- g.mapMarshalUint("32", ptr)
- case "uint16":
- g.mapMarshalUint("16", ptr)
- case "uint8":
- g.mapMarshalUint("8", ptr)
- case "float64":
- g.mapMarshalFloat("64", ptr)
- case "float32":
- g.mapMarshalFloat("32", ptr)
- default:
- // if ident is already in our spec list
- if sp, ok := g.genTypes[i.Name]; ok {
- g.mapMarshalNonPrim(sp, ptr)
- } else if i.Obj != nil {
- switch t := i.Obj.Decl.(type) {
- case *ast.TypeSpec:
- g.mapMarshalNonPrim(t, ptr)
- default:
- return errors.New("could not determine what to do with type " + i.String())
- }
- } else {
- return fmt.Errorf("Unknown type %s", i.Name)
- }
- }
- return nil
-}
-
-func (g *Gen) mapMarshalNonPrim(sp *ast.TypeSpec, ptr bool) {
- switch sp.Type.(type) {
- case *ast.StructType:
- g.mapMarshalStruct(sp, ptr)
- case *ast.ArrayType:
- g.mapMarshalArr(sp, ptr)
- }
-}
-
-func (g *Gen) mapMarshalString(ptr bool) {
- ptrStr := ""
- if ptr {
- ptrStr = "*"
- }
- err := mapMarshalTpl["string"].tpl.Execute(g.b, struct {
- Ptr string
- }{ptrStr})
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (g *Gen) mapMarshalBool(ptr bool) {
- ptrStr := ""
- if ptr {
- ptrStr = "*"
- }
- err := mapMarshalTpl["bool"].tpl.Execute(g.b, struct {
- Ptr string
- }{ptrStr})
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (g *Gen) mapMarshalInt(intLen string, ptr bool) {
- ptrStr := ""
- if ptr {
- ptrStr = "*"
- }
- err := mapMarshalTpl["int"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, ptrStr})
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (g *Gen) mapMarshalUint(intLen string, ptr bool) {
- ptrStr := ""
- if ptr {
- ptrStr = "*"
- }
- err := mapMarshalTpl["uint"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, ptrStr})
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (g *Gen) mapMarshalFloat(intLen string, ptr bool) {
- ptrStr := ""
- if ptr {
- ptrStr = "*"
- }
- err := mapMarshalTpl["float"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, ptrStr})
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (g *Gen) mapMarshalStruct(st *ast.TypeSpec, ptr bool) {
- ptrStr := ""
- if ptr {
- ptrStr = "*"
- }
- var err = mapMarshalTpl["struct"].tpl.Execute(g.b, struct {
- Ptr string
- }{ptrStr})
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (g *Gen) mapMarshalArr(st *ast.TypeSpec, ptr bool) {
- ptrStr := ""
- if ptr {
- ptrStr = "*"
- }
- var err = mapMarshalTpl["arr"].tpl.Execute(g.b, struct {
- Ptr string
- }{ptrStr})
- if err != nil {
- log.Fatal(err)
- }
-}
diff --git a/gojay/gen_map_marshal_tpl.go b/gojay/gen_map_marshal_tpl.go
@@ -1,60 +0,0 @@
-package main
-
-var mapMarshalTpl = templateList{
- "def": &genTpl{
- strTpl: "\n// MarshalJSONObject implements gojay's MarshalerJSONObject" +
- "\nfunc (v {{.StructName}}) MarshalJSONObject(enc *gojay.Encoder) {\n",
- },
- "isNil": &genTpl{
- strTpl: `
-// IsNil returns wether the structure is nil value or not
-func (v {{.StructName}}) IsNil() bool { return v == nil || len(v) == 0 }
-`,
- },
- "string": &genTpl{
- strTpl: ` for k, s := range v {
- enc.StringKey(k, {{.Ptr}}s)
- }
-`,
- },
- "int": &genTpl{
- strTpl: ` for k, s := range v {
- enc.Int{{.IntLen}}Key(k, {{.Ptr}}s)
- }
-`,
- },
- "uint": &genTpl{
- strTpl: ` for k, s := range v {
- enc.Uint{{.IntLen}}Key(k, {{.Ptr}}s)
- }
-`,
- },
- "float": &genTpl{
- strTpl: ` for k, s := range v {
- enc.Float{{.IntLen}}Key(k, {{.Ptr}}s)
- }
-`,
- },
- "bool": &genTpl{
- strTpl: ` for k, s := range v {
- enc.BoolKey(k, {{.Ptr}}s)
- }
-`,
- },
- "struct": &genTpl{
- strTpl: ` for k, s := range v {
- enc.ObjectKey(k, s)
- }
-`,
- },
- "arr": &genTpl{
- strTpl: ` for k, s := range v {
- enc.ArrayKey(k, s)
- }
-`,
- },
-}
-
-func init() {
- parseTemplates(mapMarshalTpl, "mapMarshal")
-}
diff --git a/gojay/gen_map_test.go b/gojay/gen_map_test.go
@@ -1,616 +0,0 @@
-package main
-
-import (
- "io"
- "log"
- "strings"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestGenMap(t *testing.T) {
- testCases := map[string]struct {
- input io.Reader
- expectedResult string
- }{
- "basicMapStringString": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type StrMap map[string]string
-`),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v StrMap) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
- var str string
- if err := dec.String(&str); err != nil {
- return err
- }
- v[k] = str
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (v StrMap) NKeys() int { return 0 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v StrMap) MarshalJSONObject(enc *gojay.Encoder) {
- for k, s := range v {
- enc.StringKey(k, s)
- }
-}
-
-// IsNil returns wether the structure is nil value or not
-func (v StrMap) IsNil() bool { return v == nil || len(v) == 0 }
-`,
- },
- "basicMapStringStringPtr": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type StrMap map[string]*string
-`),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v StrMap) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
- var str string
- if err := dec.String(&str); err != nil {
- return err
- }
- v[k] = &str
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (v StrMap) NKeys() int { return 0 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v StrMap) MarshalJSONObject(enc *gojay.Encoder) {
- for k, s := range v {
- enc.StringKey(k, *s)
- }
-}
-
-// IsNil returns wether the structure is nil value or not
-func (v StrMap) IsNil() bool { return v == nil || len(v) == 0 }
-`,
- },
- "basicMapStringInt": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type IntMap map[string]int
-`),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v IntMap) 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 IntMap) NKeys() int { return 0 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v IntMap) 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 IntMap) IsNil() bool { return v == nil || len(v) == 0 }
-`,
- },
- "basicMapStringIntPtr": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type IntMap map[string]*int
-`),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v IntMap) 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 IntMap) NKeys() int { return 0 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v IntMap) 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 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 }
-`,
- },
- "basicMapStringInt64Ptr": {
- 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 }
-`,
- },
- "basicMapStringUint64Ptr": {
- 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 }
-`,
- },
- "basicMapStringBoolPtr": {
- 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) {
- g, err := MakeGenFromReader(testCase.input)
- if err != nil {
- t.Fatal(err)
- }
- err = g.Gen()
- if err != nil {
- t.Fatal(err)
- }
- log.Print(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
@@ -1,242 +0,0 @@
-package main
-
-import (
- "errors"
- "fmt"
- "go/ast"
- "log"
-)
-
-func (g *Gen) mapGenNKeys(n string, count int) error {
- err := mapUnmarshalTpl["nKeys"].tpl.Execute(g.b, struct {
- NKeys int
- StructName string
- }{
- NKeys: count,
- StructName: n,
- })
- return err
-}
-
-func (g *Gen) mapGenUnmarshalObj(n string, s *ast.MapType) error {
- err := mapUnmarshalTpl["def"].tpl.Execute(g.b, struct {
- TypeName string
- }{
- TypeName: n,
- })
- if err != nil {
- return err
- }
- switch t := s.Value.(type) {
- case *ast.Ident:
- var err error
- err = g.mapGenUnmarshalIdent(t, false)
- if err != nil {
- return err
- }
- case *ast.StarExpr:
- switch ptrExp := t.X.(type) {
- case *ast.Ident:
- var err error
- err = g.mapGenUnmarshalIdent(ptrExp, true)
- if err != nil {
- return err
- }
- default:
- return fmt.Errorf("Unknown type %s", n)
- }
- }
- _, err = g.b.Write(structUnmarshalClose)
- if err != nil {
- return err
- }
- return nil
-}
-
-func (g *Gen) mapGenUnmarshalIdent(i *ast.Ident, ptr bool) error {
- switch i.String() {
- case "string":
- g.mapUnmarshalString(ptr)
- case "bool":
- g.mapUnmarshalBool(ptr)
- case "int":
- g.mapUnmarshalInt("", ptr)
- case "int64":
- g.mapUnmarshalInt("64", ptr)
- case "int32":
- g.mapUnmarshalInt("32", ptr)
- case "int16":
- g.mapUnmarshalInt("16", ptr)
- case "int8":
- g.mapUnmarshalInt("8", ptr)
- case "uint64":
- g.mapUnmarshalUint("64", ptr)
- case "uint32":
- g.mapUnmarshalUint("32", ptr)
- case "uint16":
- g.mapUnmarshalUint("16", ptr)
- case "uint8":
- g.mapUnmarshalUint("8", ptr)
- case "float64":
- g.mapUnmarshalFloat("64", ptr)
- case "float32":
- g.mapUnmarshalFloat("32", ptr)
- default:
- // if ident is already in our spec list
- if sp, ok := g.genTypes[i.Name]; ok {
- err := g.mapUnmarshalNonPrim(sp, ptr)
- if err != nil {
- return err
- }
- } else if i.Obj != nil {
- // else check the obj infos
- switch t := i.Obj.Decl.(type) {
- case *ast.TypeSpec:
- err := g.mapUnmarshalNonPrim(t, ptr)
- if err != nil {
- return err
- }
- default:
- return errors.New("could not determine what to do with type " + i.String())
- }
- } else {
- return fmt.Errorf("Unknown type %s", i.Name)
- }
- }
- return nil
-}
-
-func (g *Gen) mapUnmarshalNonPrim(sp *ast.TypeSpec, ptr bool) error {
- switch sp.Type.(type) {
- case *ast.StructType:
- g.mapUnmarshalStruct(sp, ptr)
- return nil
- case *ast.ArrayType:
- g.mapUnmarshalArr(sp, ptr)
- return nil
- }
- return errors.New("Unknown type")
-}
-
-func (g *Gen) mapUnmarshalString(ptr bool) {
- if ptr {
- err := mapUnmarshalTpl["string"].tpl.Execute(g.b, struct {
- Ptr string
- }{"&"})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := mapUnmarshalTpl["string"].tpl.Execute(g.b, struct {
- Ptr string
- }{""})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-func (g *Gen) mapUnmarshalBool(ptr bool) {
- if ptr {
- err := mapUnmarshalTpl["bool"].tpl.Execute(g.b, struct {
- Ptr string
- }{"&"})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err := mapUnmarshalTpl["bool"].tpl.Execute(g.b, struct {
- Ptr string
- }{""})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-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 {
- log.Fatal(err)
- }
- } else {
- err := mapUnmarshalTpl["int"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, ""})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-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 {
- log.Fatal(err)
- }
- } else {
- err := mapUnmarshalTpl["uint"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, ""})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-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 {
- log.Fatal(err)
- }
- } else {
- err := mapUnmarshalTpl["float"].tpl.Execute(g.b, struct {
- IntLen string
- Ptr string
- }{intLen, ""})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-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 {
- log.Fatal(err)
- }
- } else {
- err := mapUnmarshalTpl["struct"].tpl.Execute(g.b, struct {
- StructName string
- }{st.Name.String()})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-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 {
- log.Fatal(err)
- }
-}
diff --git a/gojay/gen_map_unmarshal_tpl.go b/gojay/gen_map_unmarshal_tpl.go
@@ -1,82 +0,0 @@
-package main
-
-var mapUnmarshalTpl = templateList{
- "def": &genTpl{
- strTpl: "\n// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject" +
- "\nfunc (v {{.TypeName}}) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {\n",
- },
- "nKeys": &genTpl{
- strTpl: `
-// NKeys returns the number of keys to unmarshal
-func (v {{.StructName}}) NKeys() int { return {{.NKeys}} }
-`,
- },
- "string": &genTpl{
- strTpl: ` var str string
- if err := dec.String(&str); err != nil {
- return err
- }
- v[k] = {{.Ptr}}str
-`,
- },
- "int": &genTpl{
- strTpl: ` var i int{{.IntLen}}
- if err := dec.Int{{.IntLen}}(&i); err != nil {
- return err
- }
- v[k] = {{.Ptr}}i
-`,
- },
- "uint": &genTpl{
- strTpl: ` var i uint{{.IntLen}}
- if err := dec.Uint{{.IntLen}}(&i); err != nil {
- return err
- }
- v[k] = {{.Ptr}}i
-`,
- },
- "float": &genTpl{
- strTpl: ` var i float{{.IntLen}}
- if err := dec.Float{{.IntLen}}(&i); err != nil {
- return err
- }
- v[k] = {{.Ptr}}i
-`,
- },
- "bool": &genTpl{
- strTpl: ` var b bool
- if err := dec.Bool(&b); err != nil {
- return err
- }
- v[k] = {{.Ptr}}b
-`,
- },
- "struct": &genTpl{
- strTpl: ` var s = {{.StructName}}{}
- if err := dec.Object(&s); err != nil {
- return err
- }
- v[k] = s
-`,
- },
- "structPtr": &genTpl{
- strTpl: ` var s = &{{.StructName}}{}
- if err := dec.Object(s); err != nil {
- return err
- }
- v[k] = s
-`,
- },
- "arr": &genTpl{
- strTpl: ` var s = &{{.StructName}}{}
- if err := dec.Array(s); err != nil {
- return err
- }
- v[k] = s
-`,
- },
-}
-
-func init() {
- parseTemplates(mapUnmarshalTpl, "mapUnmarshal")
-}
diff --git a/gojay/gen_parse.go b/gojay/gen_parse.go
@@ -1,63 +0,0 @@
-//+build !test
-
-package main
-
-import (
- "go/ast"
- "go/parser"
- "go/token"
- "os"
-)
-
-func (g *Gen) parse() error {
- var f, err = os.Stat(g.src)
- if err != nil {
- return err
- }
- if f.IsDir() {
- err = g.parseDir()
- } else {
- err = g.parseFile()
- }
- return err
-}
-
-func (g *Gen) parseDir() error {
- // parse the given path
- fset := token.NewFileSet()
- pkgs, err := parser.ParseDir(fset, g.src, nil, parser.ParseComments)
- if err != nil {
- return err
- }
- // range across packages
- for pkgName, pkg := range pkgs {
- v := newVisitor(g, pkgName)
- g.pkg = pkgName
- // range on files in package
- for _, f := range pkg.Files {
- ast.Walk(v, f)
- if err != nil {
- return err
- }
- }
- g.vis = v
- }
- return nil
-}
-
-func (g *Gen) parseFile() error {
- // parse the given path
- fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, g.src, nil, parser.ParseComments)
- if err != nil {
- return err
- }
- g.pkg = f.Name.Name
- v := newVisitor(g, g.pkg)
- ast.Walk(v, f)
- if err != nil {
- return err
- }
- g.vis = v
- return nil
-}
diff --git a/gojay/gen_struct_marshal.go b/gojay/gen_struct_marshal.go
@@ -1,290 +0,0 @@
-package main
-
-import (
- "fmt"
- "go/ast"
- "log"
-)
-
-func (g *Gen) structGenIsNil(n string) error {
- err := structMarshalTpl["isNil"].tpl.Execute(g.b, struct {
- StructName string
- }{
- StructName: n,
- })
- return err
-}
-
-func (g *Gen) structGenMarshalObj(n string, s *ast.StructType) (int, error) {
- err := structMarshalTpl["def"].tpl.Execute(g.b, struct {
- StructName string
- }{
- StructName: n,
- })
- if err != nil {
- return 0, err
- }
- keys := 0
- if len(s.Fields.List) > 0 {
- // TODO: check tags
- for _, field := range s.Fields.List {
- // check if has hide tag
- var omitEmpty string
- if field.Tag != nil {
- if hasTagMarshalHide(field.Tag) {
- continue
- }
- if hasTagOmitEmpty(field.Tag) {
- omitEmpty = omitEmptyFuncName
- }
- }
- switch t := field.Type.(type) {
- case *ast.Ident:
- var err error
- keys, err = g.structGenMarshalIdent(field, t, keys, omitEmpty, false)
- if err != nil {
- return 0, err
- }
- case *ast.StarExpr:
- switch ptrExp := t.X.(type) {
- case *ast.Ident:
- var err error
- keys, err = g.structGenMarshalIdent(field, ptrExp, keys, omitEmpty, true)
- if err != nil {
- return 0, err
- }
- default:
- return 0, fmt.Errorf("Unknown type %s", n)
- }
- }
- }
- }
- _, err = g.b.Write([]byte("}\n"))
- if err != nil {
- return 0, err
- }
- return keys, nil
-}
-
-func (g *Gen) structGenMarshalIdent(field *ast.Field, i *ast.Ident, keys int, omitEmpty string, ptr bool) (int, error) {
- var keyV = getStructFieldJSONKey(field)
-
- switch i.String() {
- case "string":
- g.structMarshalString(field, keyV, omitEmpty, ptr)
- keys++
- case "bool":
- g.structMarshalBool(field, keyV, omitEmpty, ptr)
- keys++
- case "int":
- g.structMarshalInt(field, keyV, "", omitEmpty, ptr)
- keys++
- case "int64":
- g.structMarshalInt(field, keyV, "64", omitEmpty, ptr)
- keys++
- case "int32":
- g.structMarshalInt(field, keyV, "32", omitEmpty, ptr)
- keys++
- case "int16":
- g.structMarshalInt(field, keyV, "16", omitEmpty, ptr)
- keys++
- case "int8":
- g.structMarshalInt(field, keyV, "8", omitEmpty, ptr)
- keys++
- case "uint64":
- g.structMarshalUint(field, keyV, "64", omitEmpty, ptr)
- keys++
- case "uint32":
- g.structMarshalUint(field, keyV, "32", omitEmpty, ptr)
- keys++
- case "uint16":
- g.structMarshalUint(field, keyV, "16", omitEmpty, ptr)
- keys++
- case "uint8":
- g.structMarshalUint(field, keyV, "8", omitEmpty, ptr)
- keys++
- case "float64":
- g.structMarshalFloat(field, keyV, "64", omitEmpty, ptr)
- keys++
- case "float32":
- g.structMarshalFloat(field, keyV, "32", omitEmpty, ptr)
- keys++
- default:
- // if ident is already in our spec list
- if sp, ok := g.genTypes[i.Name]; ok {
- err := g.structMarshalNonPrim(field, keyV, sp, omitEmpty, ptr)
- if err != nil {
- return 0, err
- }
- keys++
- } else if i.Obj != nil {
- switch t := i.Obj.Decl.(type) {
- case *ast.TypeSpec:
- var err = g.structMarshalNonPrim(field, keyV, t, omitEmpty, ptr)
- if err != nil {
- return 0, err
- }
- keys++
- default:
- g.structMarshalAny(field, keyV, sp, ptr)
- keys++
- }
- } else {
- g.structMarshalAny(field, keyV, sp, ptr)
- keys++
- }
- }
- return keys, nil
-}
-
-func (g *Gen) structMarshalNonPrim(field *ast.Field, keyV string, sp *ast.TypeSpec, omitEmpty string, ptr bool) error {
- switch sp.Type.(type) {
- case *ast.StructType:
- g.structMarshalStruct(field, keyV, sp, omitEmpty, ptr)
- return nil
- case *ast.ArrayType:
- g.structMarshalArr(field, keyV, sp, omitEmpty, ptr)
- return nil
- default:
- g.structMarshalAny(field, keyV, sp, ptr)
- }
- return nil
-}
-
-func (g *Gen) structMarshalString(field *ast.Field, keyV string, omitEmpty string, ptr bool) {
- key := field.Names[0].String()
- ptrStr := ""
- if ptr {
- ptrStr = "*"
- }
- err := structMarshalTpl["string"].tpl.Execute(g.b, struct {
- Field string
- Key string
- OmitEmpty string
- Ptr string
- }{key, keyV, omitEmpty, ptrStr})
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (g *Gen) structMarshalBool(field *ast.Field, keyV string, omitEmpty string, ptr bool) {
- key := field.Names[0].String()
- ptrStr := ""
- if ptr {
- ptrStr = "*"
- }
- err := structMarshalTpl["bool"].tpl.Execute(g.b, struct {
- Field string
- Key string
- OmitEmpty string
- Ptr string
- }{key, keyV, omitEmpty, ptrStr})
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (g *Gen) structMarshalInt(field *ast.Field, keyV string, intLen string, omitEmpty string, ptr bool) {
- key := field.Names[0].String()
- ptrStr := ""
- if ptr {
- ptrStr = "*"
- }
- err := structMarshalTpl["int"].tpl.Execute(g.b, struct {
- Field string
- IntLen string
- Key string
- OmitEmpty string
- Ptr string
- }{key, intLen, keyV, omitEmpty, ptrStr})
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (g *Gen) structMarshalUint(field *ast.Field, keyV string, intLen string, omitEmpty string, ptr bool) {
- key := field.Names[0].String()
- ptrStr := ""
- if ptr {
- ptrStr = "*"
- }
- err := structMarshalTpl["uint"].tpl.Execute(g.b, struct {
- Field string
- IntLen string
- Key string
- OmitEmpty string
- Ptr string
- }{key, intLen, keyV, omitEmpty, ptrStr})
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (g *Gen) structMarshalFloat(field *ast.Field, keyV string, intLen string, omitEmpty string, ptr bool) {
- key := field.Names[0].String()
- ptrStr := ""
- if ptr {
- ptrStr = "*"
- }
- err := structMarshalTpl["float"].tpl.Execute(g.b, struct {
- Field string
- IntLen string
- Key string
- OmitEmpty string
- Ptr string
- }{key, intLen, keyV, omitEmpty, ptrStr})
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (g *Gen) structMarshalStruct(field *ast.Field, keyV string, st *ast.TypeSpec, omitEmpty string, ptr bool) {
- key := field.Names[0].String()
- ptrStr := ""
- if ptr {
- ptrStr = "*"
- }
- var err = structMarshalTpl["struct"].tpl.Execute(g.b, struct {
- Key string
- Field string
- OmitEmpty string
- Ptr string
- }{keyV, key, omitEmpty, ptrStr})
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (g *Gen) structMarshalArr(field *ast.Field, keyV string, st *ast.TypeSpec, omitEmpty string, ptr bool) {
- key := field.Names[0].String()
- ptrStr := ""
- if ptr {
- ptrStr = "*"
- }
- var err = structMarshalTpl["arr"].tpl.Execute(g.b, struct {
- Key string
- Field string
- OmitEmpty string
- Ptr string
- }{keyV, key, omitEmpty, ptrStr})
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (g *Gen) structMarshalAny(field *ast.Field, keyV string, st *ast.TypeSpec, ptr bool) {
- key := field.Names[0].String()
- ptrStr := ""
- if ptr {
- ptrStr = "*"
- }
- var err = structMarshalTpl["any"].tpl.Execute(g.b, struct {
- Key string
- Field string
- Ptr string
- }{keyV, key, ptrStr})
- if err != nil {
- log.Fatal(err)
- }
-}
diff --git a/gojay/gen_struct_marshal_tpl.go b/gojay/gen_struct_marshal_tpl.go
@@ -1,42 +0,0 @@
-package main
-
-var structMarshalTpl = templateList{
- "def": &genTpl{
- strTpl: "\n// MarshalJSONObject implements gojay's MarshalerJSONObject" +
- "\nfunc (v *{{.StructName}}) MarshalJSONObject(enc *gojay.Encoder) {\n",
- },
- "isNil": &genTpl{
- strTpl: `
-// IsNil returns wether the structure is nil value or not
-func (v *{{.StructName}}) IsNil() bool { return v == nil }
-`,
- },
- "string": &genTpl{
- strTpl: "\tenc.StringKey{{.OmitEmpty}}(\"{{.Key}}\", {{.Ptr}}v.{{.Field}})\n",
- },
- "int": &genTpl{
- strTpl: "\tenc.Int{{.IntLen}}Key{{.OmitEmpty}}(\"{{.Key}}\", {{.Ptr}}v.{{.Field}})\n",
- },
- "uint": &genTpl{
- strTpl: "\tenc.Uint{{.IntLen}}Key{{.OmitEmpty}}(\"{{.Key}}\", {{.Ptr}}v.{{.Field}})\n",
- },
- "float": &genTpl{
- strTpl: "\tenc.Float{{.IntLen}}Key{{.OmitEmpty}}(\"{{.Key}}\", {{.Ptr}}v.{{.Field}})\n",
- },
- "bool": &genTpl{
- strTpl: "\tenc.BoolKey{{.OmitEmpty}}(\"{{.Key}}\", {{.Ptr}}v.{{.Field}})\n",
- },
- "struct": &genTpl{
- strTpl: "\tenc.ObjectKey{{.OmitEmpty}}(\"{{.Key}}\", v.{{.Field}})\n",
- },
- "arr": &genTpl{
- strTpl: "\tenc.ArrayKey{{.OmitEmpty}}(\"{{.Key}}\", v.{{.Field}})\n",
- },
- "any": &genTpl{
- strTpl: "\tenc.AnyKey(\"{{.Key}}\", v.{{.Field}})\n",
- },
-}
-
-func init() {
- parseTemplates(structMarshalTpl, "structMarshal")
-}
diff --git a/gojay/gen_struct_test.go b/gojay/gen_struct_test.go
@@ -1,433 +0,0 @@
-package main
-
-import (
- "io"
- "strings"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestGenStruct(t *testing.T) {
- testCases := map[string]struct {
- input io.Reader
- expectedResult string
- }{
- "basicStruct": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type Struct struct{
- Int int
- Int8 int8
- Int16 int16
- Int32 int32
- Int64 int64
- Uint8 uint8
- Uint16 uint16
- Uint32 uint32
- Uint64 uint64
- Float64 float64
- Float32 float32
- Str string
- Bool bool
- Unknown UnknownType
-}
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v *Struct) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
- switch k {
- case "int":
- return dec.Int(&v.Int)
- case "int8":
- return dec.Int8(&v.Int8)
- case "int16":
- return dec.Int16(&v.Int16)
- case "int32":
- 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 "float64":
- return dec.Float64(&v.Float64)
- case "float32":
- return dec.Float32(&v.Float32)
- case "str":
- return dec.String(&v.Str)
- case "bool":
- return dec.Bool(&v.Bool)
- case "unknown":
- return dec.Any(&v.Unknown)
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (v *Struct) NKeys() int { return 14 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v *Struct) MarshalJSONObject(enc *gojay.Encoder) {
- enc.IntKey("int", v.Int)
- enc.Int8Key("int8", v.Int8)
- 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.Float64Key("float64", v.Float64)
- enc.Float32Key("float32", v.Float32)
- enc.StringKey("str", v.Str)
- enc.BoolKey("bool", v.Bool)
- enc.AnyKey("unknown", v.Unknown)
-}
-
-// IsNil returns wether the structure is nil value or not
-func (v *Struct) IsNil() bool { return v == nil }
-`,
- },
- "basicStructPtr": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type Struct struct{
- Int *int
- Str *string
-}
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v *Struct) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
- switch k {
- case "int":
- return dec.Int(v.Int)
- case "str":
- return dec.String(v.Str)
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (v *Struct) NKeys() int { return 2 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v *Struct) MarshalJSONObject(enc *gojay.Encoder) {
- enc.IntKey("int", *v.Int)
- enc.StringKey("str", *v.Str)
-}
-
-// IsNil returns wether the structure is nil value or not
-func (v *Struct) IsNil() bool { return v == nil }
-`,
- },
- "basicStructTags": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type Struct struct{
- Int int ` + "`gojay:\"someInt\"`" + `
- Str string ` + "`gojay:\"someStr\"`" + `
-}
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v *Struct) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
- switch k {
- case "someInt":
- return dec.Int(&v.Int)
- case "someStr":
- return dec.String(&v.Str)
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (v *Struct) NKeys() int { return 2 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v *Struct) MarshalJSONObject(enc *gojay.Encoder) {
- enc.IntKey("someInt", v.Int)
- enc.StringKey("someStr", v.Str)
-}
-
-// IsNil returns wether the structure is nil value or not
-func (v *Struct) IsNil() bool { return v == nil }
-`,
- },
- "basicStructTagsHideUnmarshal": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type Struct struct{
- Int int ` + "`gojay:\"-u\"`" + `
- Str string ` + "`gojay:\"-u\"`" + `
-}
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v *Struct) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
- switch k {
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (v *Struct) NKeys() int { return 0 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v *Struct) MarshalJSONObject(enc *gojay.Encoder) {
- enc.IntKey("int", v.Int)
- enc.StringKey("str", v.Str)
-}
-
-// IsNil returns wether the structure is nil value or not
-func (v *Struct) IsNil() bool { return v == nil }
-`,
- },
- "basicStructTagsHideUnmarshal2": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type Struct struct{
- Int int ` + "`gojay:\"someInt,-u\"`" + `
- Str string ` + "`gojay:\"someStr,-u\"`" + `
-}
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v *Struct) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
- switch k {
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (v *Struct) NKeys() int { return 0 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v *Struct) MarshalJSONObject(enc *gojay.Encoder) {
- enc.IntKey("someInt", v.Int)
- enc.StringKey("someStr", v.Str)
-}
-
-// IsNil returns wether the structure is nil value or not
-func (v *Struct) IsNil() bool { return v == nil }
-`,
- },
- "basicStructTagsHideUnmarshal3": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type Struct struct{
- Int int ` + "`gojay:\"someInt,-m\"`" + `
- Str string ` + "`gojay:\"someStr,-m\"`" + `
-}
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v *Struct) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
- switch k {
- case "someInt":
- return dec.Int(&v.Int)
- case "someStr":
- return dec.String(&v.Str)
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (v *Struct) NKeys() int { return 2 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v *Struct) MarshalJSONObject(enc *gojay.Encoder) {
-}
-
-// IsNil returns wether the structure is nil value or not
-func (v *Struct) IsNil() bool { return v == nil }
-`,
- },
- "basicStructTagsHideUnmarshal4": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type Struct struct{
- Int int ` + "`gojay:\"-\"`" + `
- Str string ` + "`gojay:\"-\"`" + `
-}
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v *Struct) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
- switch k {
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (v *Struct) NKeys() int { return 0 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v *Struct) MarshalJSONObject(enc *gojay.Encoder) {
-}
-
-// IsNil returns wether the structure is nil value or not
-func (v *Struct) IsNil() bool { return v == nil }
-`,
- },
- "complexStructStructTag": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type Struct struct{
- Struct Struct ` + "`gojay:\"someStruct\"`" + `
-}
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v *Struct) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
- switch k {
- case "someStruct":
- if v.Struct == nil {
- v.Struct = Struct{}
- }
- return dec.Object(v.Struct)
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (v *Struct) NKeys() int { return 1 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v *Struct) MarshalJSONObject(enc *gojay.Encoder) {
- enc.ObjectKey("someStruct", v.Struct)
-}
-
-// IsNil returns wether the structure is nil value or not
-func (v *Struct) IsNil() bool { return v == nil }
-`,
- },
- "complexStructStructPtrTag": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type Struct struct{
- Struct *Struct ` + "`gojay:\"someStruct\"`" + `
-}
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v *Struct) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
- switch k {
- case "someStruct":
- if v.Struct == nil {
- v.Struct = &Struct{}
- }
- return dec.Object(v.Struct)
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (v *Struct) NKeys() int { return 1 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v *Struct) MarshalJSONObject(enc *gojay.Encoder) {
- enc.ObjectKey("someStruct", v.Struct)
-}
-
-// IsNil returns wether the structure is nil value or not
-func (v *Struct) IsNil() bool { return v == nil }
-`,
- },
- "complexStructStructPtrTagOmitEmpty": {
- input: strings.NewReader(`package test
-
-//gojay:json
-type Struct struct{
- Struct *Struct ` + "`gojay:\"someStruct,omitempty\"`" + `
-}
- `),
- expectedResult: `package
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v *Struct) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
- switch k {
- case "someStruct":
- if v.Struct == nil {
- v.Struct = &Struct{}
- }
- return dec.Object(v.Struct)
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (v *Struct) NKeys() int { return 1 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v *Struct) MarshalJSONObject(enc *gojay.Encoder) {
- enc.ObjectKeyOmitEmpty("someStruct", v.Struct)
-}
-
-// IsNil returns wether the structure is nil value or not
-func (v *Struct) IsNil() bool { return v == nil }
-`,
- },
- }
- for n, testCase := range testCases {
- t.Run(n, func(t *testing.T) {
- g, err := MakeGenFromReader(testCase.input)
- if err != nil {
- t.Fatal(err)
- }
- err = g.Gen()
- if err != nil {
- t.Fatal(err)
- }
- assert.Equal(
- t,
- string(genHeader)+testCase.expectedResult,
- g.b.String(),
- )
- })
- }
-}
diff --git a/gojay/gen_struct_unmarshal.go b/gojay/gen_struct_unmarshal.go
@@ -1,378 +0,0 @@
-package main
-
-import (
- "fmt"
- "go/ast"
- "log"
-)
-
-var structUnmarshalSwitchOpen = []byte("\tswitch k {\n")
-var structUnmarshalClose = []byte("\treturn nil\n}\n")
-
-func (g *Gen) structGenNKeys(n string, count int) error {
- err := structUnmarshalTpl["nKeys"].tpl.Execute(g.b, struct {
- NKeys int
- StructName string
- }{
- NKeys: count,
- StructName: n,
- })
- return err
-}
-
-func (g *Gen) structGenUnmarshalObj(n string, s *ast.StructType) (int, error) {
- err := structUnmarshalTpl["def"].tpl.Execute(g.b, struct {
- StructName string
- }{
- StructName: n,
- })
- if err != nil {
- return 0, err
- }
- keys := 0
- if len(s.Fields.List) > 0 {
- // open switch statement
- g.b.Write(structUnmarshalSwitchOpen)
- // TODO: check tags
- // check type of field
- // add accordingly
- for _, field := range s.Fields.List {
- // check if has hide tag
- if field.Tag != nil && hasTagUnmarshalHide(field.Tag) {
- continue
- }
- switch t := field.Type.(type) {
- case *ast.Ident:
- var err error
- keys, err = g.structGenUnmarshalIdent(field, t, keys, false)
- if err != nil {
- return 0, err
- }
- case *ast.StarExpr:
- switch ptrExp := t.X.(type) {
- case *ast.Ident:
- var err error
- keys, err = g.structGenUnmarshalIdent(field, ptrExp, keys, true)
- if err != nil {
- return 0, err
- }
- default:
- return 0, fmt.Errorf("Unknown type %s", n)
- }
- }
- }
- // close switch statement
- g.b.Write([]byte("\t}\n"))
- }
- _, err = g.b.Write(structUnmarshalClose)
- if err != nil {
- return 0, err
- }
- return keys, nil
-}
-
-func (g *Gen) structGenUnmarshalIdent(field *ast.Field, i *ast.Ident, keys int, ptr bool) (int, error) {
- var keyV = getStructFieldJSONKey(field)
-
- switch i.String() {
- case "string":
- g.structUnmarshalString(field, keyV, ptr)
- keys++
- case "bool":
- g.structUnmarshalBool(field, keyV, ptr)
- keys++
- case "int":
- g.structUnmarshalInt(field, keyV, "", ptr)
- keys++
- case "int64":
- g.structUnmarshalInt(field, keyV, "64", ptr)
- keys++
- case "int32":
- g.structUnmarshalInt(field, keyV, "32", ptr)
- keys++
- case "int16":
- g.structUnmarshalInt(field, keyV, "16", ptr)
- keys++
- case "int8":
- g.structUnmarshalInt(field, keyV, "8", ptr)
- keys++
- case "uint64":
- g.structUnmarshalUint(field, keyV, "64", ptr)
- keys++
- case "uint32":
- g.structUnmarshalUint(field, keyV, "32", ptr)
- keys++
- case "uint16":
- g.structUnmarshalUint(field, keyV, "16", ptr)
- keys++
- case "uint8":
- g.structUnmarshalUint(field, keyV, "8", ptr)
- keys++
- case "float64":
- g.structUnmarshalFloat(field, keyV, "64", ptr)
- keys++
- case "float32":
- g.structUnmarshalFloat(field, keyV, "32", ptr)
- keys++
- default:
- // if ident is already in our spec list
- if sp, ok := g.genTypes[i.Name]; ok {
- err := g.structUnmarshalNonPrim(field, keyV, sp, ptr)
- if err != nil {
- return 0, err
- }
- keys++
- } else if i.Obj != nil {
- // else check the obj infos
- switch t := i.Obj.Decl.(type) {
- case *ast.TypeSpec:
- err := g.structUnmarshalNonPrim(field, keyV, t, ptr)
- if err != nil {
- return 0, err
- }
- keys++
- default:
- g.structUnmarshalAny(field, keyV, sp, ptr)
- keys++
- }
- } else {
- g.structUnmarshalAny(field, keyV, sp, ptr)
- keys++
- }
- }
- return keys, nil
-}
-
-func (g *Gen) structUnmarshalNonPrim(field *ast.Field, keyV string, sp *ast.TypeSpec, ptr bool) error {
- switch sp.Type.(type) {
- case *ast.StructType:
- g.structUnmarshalStruct(field, keyV, sp, ptr)
- return nil
- case *ast.ArrayType:
- g.structUnmarshalArr(field, keyV, sp, ptr)
- return nil
- default:
- g.structUnmarshalAny(field, keyV, sp, ptr)
- return nil
- }
-}
-
-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 {
- log.Fatal(err)
- }
- if ptr {
- err = structUnmarshalTpl["string"].tpl.Execute(g.b, struct {
- Field string
- Ptr string
- }{key, ""})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err = structUnmarshalTpl["string"].tpl.Execute(g.b, struct {
- Field string
- Ptr string
- }{key, "&"})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-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 {
- log.Fatal(err)
- }
- if ptr {
- err = structUnmarshalTpl["bool"].tpl.Execute(g.b, struct {
- Field string
- Ptr string
- }{key, ""})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err = structUnmarshalTpl["bool"].tpl.Execute(g.b, struct {
- Field string
- Ptr string
- }{key, "&"})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-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 {
- log.Fatal(err)
- }
- if ptr {
- err = structUnmarshalTpl["int"].tpl.Execute(g.b, struct {
- Field string
- IntLen string
- Ptr string
- }{key, intLen, ""})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err = structUnmarshalTpl["int"].tpl.Execute(g.b, struct {
- Field string
- IntLen string
- Ptr string
- }{key, intLen, "&"})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-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 {
- log.Fatal(err)
- }
- if ptr {
- err = structUnmarshalTpl["uint"].tpl.Execute(g.b, struct {
- Field string
- IntLen string
- Ptr string
- }{key, intLen, ""})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err = structUnmarshalTpl["uint"].tpl.Execute(g.b, struct {
- Field string
- IntLen string
- Ptr string
- }{key, intLen, "&"})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-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 {
- log.Fatal(err)
- }
- if ptr {
- err = structUnmarshalTpl["float"].tpl.Execute(g.b, struct {
- Field string
- IntLen string
- Ptr string
- }{key, intLen, ""})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err = structUnmarshalTpl["float"].tpl.Execute(g.b, struct {
- Field string
- IntLen string
- Ptr string
- }{key, intLen, "&"})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-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 {
- log.Fatal(err)
- }
- if ptr {
- err = structUnmarshalTpl["structPtr"].tpl.Execute(g.b, struct {
- Field string
- StructName string
- }{key, st.Name.String()})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err = structUnmarshalTpl["struct"].tpl.Execute(g.b, struct {
- Field string
- StructName string
- }{key, st.Name.String()})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
-
-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 {
- log.Fatal(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)
- }
- }
-}
-
-func (g *Gen) structUnmarshalAny(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 {
- log.Fatal(err)
- }
- if ptr {
- err = structUnmarshalTpl["anyPtr"].tpl.Execute(g.b, struct {
- Field string
- }{key})
- if err != nil {
- log.Fatal(err)
- }
- } else {
- err = structUnmarshalTpl["any"].tpl.Execute(g.b, struct {
- Field string
- }{key})
- if err != nil {
- log.Fatal(err)
- }
- }
-}
diff --git a/gojay/gen_struct_unmarshal_tpl.go b/gojay/gen_struct_unmarshal_tpl.go
@@ -1,72 +0,0 @@
-package main
-
-var structUnmarshalTpl = templateList{
- "def": &genTpl{
- strTpl: "\n// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject" +
- "\nfunc (v *{{.StructName}}) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {\n",
- },
- "nKeys": &genTpl{
- strTpl: `
-// NKeys returns the number of keys to unmarshal
-func (v *{{.StructName}}) NKeys() int { return {{.NKeys}} }
-`,
- },
- "case": &genTpl{
- strTpl: "\tcase \"{{.Key}}\":\n",
- },
- "string": &genTpl{
- strTpl: "\t\treturn dec.String({{.Ptr}}v.{{.Field}})\n",
- },
- "int": &genTpl{
- strTpl: "\t\treturn dec.Int{{.IntLen}}({{.Ptr}}v.{{.Field}})\n",
- },
- "uint": &genTpl{
- strTpl: "\t\treturn dec.Uint{{.IntLen}}({{.Ptr}}v.{{.Field}})\n",
- },
- "float": &genTpl{
- strTpl: "\t\treturn dec.Float{{.IntLen}}({{.Ptr}}v.{{.Field}})\n",
- },
- "bool": &genTpl{
- strTpl: "\t\treturn dec.Bool({{.Ptr}}v.{{.Field}})\n",
- },
- "struct": &genTpl{
- strTpl: ` if v.{{.Field}} == nil {
- v.{{.Field}} = {{.StructName}}{}
- }
- return dec.Object(v.{{.Field}})
-`,
- },
- "structPtr": &genTpl{
- strTpl: ` if v.{{.Field}} == nil {
- v.{{.Field}} = &{{.StructName}}{}
- }
- return dec.Object(v.{{.Field}})
-`,
- },
- "arr": &genTpl{
- strTpl: ` if v.{{.Field}} == nil {
- arr := make({{.TypeName}}, 0)
- v.{{.Field}} = arr
- }
- return dec.Array(&v.{{.Field}})
-`,
- },
- "arrPtr": &genTpl{
- strTpl: ` if v.{{.Field}} == nil {
- arr := make({{.TypeName}}, 0)
- v.{{.Field}} = &arr
- }
- return dec.Array(v.{{.Field}})
-`,
- },
- "any": &genTpl{
- strTpl: "\t\treturn dec.Any(&v.{{.Field}})\n",
- },
- "anyPtr": &genTpl{
- strTpl: "\t\treturn dec.Any(v.{{.Field}})\n",
- },
-}
-
-func init() {
- parseTemplates(structUnmarshalTpl, "structUnmarshal")
-}
diff --git a/gojay/gen_stuct.go b/gojay/gen_stuct.go
@@ -1,30 +0,0 @@
-package main
-
-import (
- "go/ast"
- "strings"
-)
-
-func getStructFieldJSONKey(field *ast.Field) string {
- var keyV string
- if field.Tag != nil {
- keyV = tagKeyName(field.Tag)
- }
- if keyV == "" {
- keyV = strings.ToLower(field.Names[0].String()[:1]) + field.Names[0].String()[1:]
- }
- return keyV
-}
-
-func (g *Gen) genStruct(n string, s *ast.StructType) error {
- keys, err := g.structGenUnmarshalObj(n, s)
- if err != nil {
- return err
- }
- err = g.structGenNKeys(n, keys)
- keys, err = g.structGenMarshalObj(n, s)
- if err != nil {
- return err
- }
- return g.structGenIsNil(n)
-}
diff --git a/gojay/gen_tag.go b/gojay/gen_tag.go
@@ -1,65 +0,0 @@
-package main
-
-import (
- "go/ast"
- "log"
-
- "github.com/fatih/structtag"
-)
-
-const gojayTag = "gojay"
-const hideTag = "-"
-const unmarshalHideTag = "-u"
-const marshalHideTag = "-m"
-const omitEmptyTag = "omitempty"
-
-func getGojayTagValue(tags *ast.BasicLit) (*structtag.Tag, error) {
- t, err := structtag.Parse(tags.Value[1 : len(tags.Value)-1])
- if err != nil {
- return nil, err
- }
- v, err := t.Get(gojayTag)
- if err != nil {
- return nil, err
- }
- return v, nil
-}
-
-func hasTagUnmarshalHide(tags *ast.BasicLit) bool {
- v, err := getGojayTagValue(tags)
- if err != nil {
- log.Print(err)
- return false
- }
- return (v.Name == unmarshalHideTag || v.Name == hideTag) || v.HasOption(unmarshalHideTag)
-}
-
-func hasTagMarshalHide(tags *ast.BasicLit) bool {
- v, err := getGojayTagValue(tags)
- if err != nil {
- log.Print(err)
- return false
- }
- return (v.Name == marshalHideTag || v.Name == hideTag) || v.HasOption(marshalHideTag)
-}
-
-func hasTagOmitEmpty(tags *ast.BasicLit) bool {
- v, err := getGojayTagValue(tags)
- if err != nil {
- log.Print(err)
- return false
- }
- return v.Name == omitEmptyTag || v.HasOption(omitEmptyTag)
-}
-
-func tagKeyName(tags *ast.BasicLit) string {
- v, err := getGojayTagValue(tags)
- if err != nil {
- log.Print(err)
- return ""
- }
- if v.Name == hideTag || v.Name == unmarshalHideTag || v.Name == marshalHideTag {
- return ""
- }
- return v.Name
-}
diff --git a/gojay/gen_test.go b/gojay/gen_test.go
@@ -1,24 +0,0 @@
-package main
-
-import (
- "go/ast"
- "go/parser"
- "go/token"
- "io"
-)
-
-func MakeGenFromReader(input io.Reader) (*Gen, error) {
- 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)
- ast.Walk(v, f)
- if err != nil {
- return nil, err
- }
- g.vis = v
- return g, nil
-}
diff --git a/gojay/gojay.go b/gojay/gojay.go
@@ -0,0 +1,23 @@
+package main
+
+import (
+ "flag"
+ "github.com/francoispqt/gojay/gojay/codegen"
+ "log"
+)
+
+var pkg = flag.String("pkg", "", "the package name of the generated file")
+var dst = flag.String("o", "", "destination file to output generated code")
+var src = flag.String("s", "", "source dir or file (absolute or relative path)")
+var types = flag.String("t", "", "types to generate")
+var annotation = flag.String("a", "json", "annotation tag (default json)")
+var poolObjects = flag.String("p", "", "generate code to reuse objects using sync.Pool")
+
+func main() {
+ flag.Parse()
+ options := codegen.NewOptionsWithFlagSet(flag.CommandLine)
+ gen := codegen.NewGenerator(options)
+ if err := gen.Generate(); err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/gojay/main.go b/gojay/main.go
@@ -1,121 +0,0 @@
-//+build !test
-
-package main
-
-import (
- "errors"
- "flag"
- "io/ioutil"
- "log"
- "os"
- "path/filepath"
- "strings"
-)
-
-var dst = flag.String("o", "", "destination file to output generated implementations")
-var src = flag.String("s", "", "source dir or file (absolute or relative path)")
-var pkg = flag.String("p", "", "go package")
-var types = flag.String("t", "", "types to generate")
-
-var ErrNoPathProvided = errors.New("You must provide a path or a package name")
-
-type stringWriter interface {
- WriteString(string) (int, error)
-}
-
-func hasAnnotation(fP string) bool {
- b, err := ioutil.ReadFile(fP)
- if err != nil {
- log.Fatal(err)
- }
- return strings.Contains(string(b), gojayAnnotation)
-}
-
-func resolvePath(p string) (string, error) {
- if fullPath, err := filepath.Abs(p); err != nil {
- return "", err
- } else if _, err := os.Stat(fullPath); err != nil {
- return "", err
- } else {
- return fullPath, nil
- }
-}
-
-// getPath returns either the path given as argument or current working directory
-func getPath() (string, error) {
- // if pkg is set, resolve pkg path
- if *pkg != "" {
- return resolvePath(os.Getenv("GOPATH") + "/src/" + *pkg)
- } else if *src != "" { // if src is present parse from src
- return resolvePath(*src)
- } 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]
- return resolvePath(os.Getenv("GOPATH") + "/src/" + os.Args[1])
- }
- return "", ErrNoPathProvided
-}
-
-// getTypes returns the types to be parsed
-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
-}
-
-// getOutput returns the output
-func getOutput() (stringWriter, error) {
- if *dst != "" {
- p, err := filepath.Abs(*dst)
- if err != nil {
- return nil, err
- }
- return os.OpenFile(p, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
- } else if len(os.Args) > 3 && *src == "" && *types == "" {
- p, err := filepath.Abs(os.Args[3])
- if err != nil {
- return nil, err
- }
- return os.OpenFile(p, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
- }
- return os.Stdout, nil
-}
-
-func parseArgs() (p string, t []string, err error) {
- flag.Parse()
- 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, t)
- err = g.parse()
- if err != nil {
- log.Fatal(err)
- return
- }
- // generate output
- err = g.Gen()
- if err != nil {
- log.Fatal(err)
- return
- }
- var o stringWriter
- o, err = getOutput()
- if err != nil {
- log.Fatal(err)
- return
- }
- // write content to output
- o.WriteString(g.b.String())
-}
diff --git a/gojay/tests/maps.go b/gojay/tests/maps.go
@@ -1,4 +0,0 @@
-package tests
-
-//gojay:json
-type MapStringInt map[string]int
diff --git a/gojay/tests/slices.go b/gojay/tests/slices.go
@@ -1,16 +0,0 @@
-package tests
-
-//gojay:json
-type StrSlice []string
-
-//gojay:json
-type IntSlice []int
-
-//gojay:json
-type BoolSlice []bool
-
-//gojay:json
-type StructSlice []*A
-
-//gojay:json
-type SliceSlice []*StrSlice
diff --git a/gojay/tests/structs.go b/gojay/tests/structs.go
@@ -1,44 +0,0 @@
-package tests
-
-//gojay:json
-type A struct {
- Str string `gojay:"string"`
- Bool bool
- Int int
- Int64 int64
- Int32 int32
- Int16 int16
- Int8 int8
- Uint64 uint64
- Uint32 uint32
- Uint16 uint16
- Uint8 uint8
- Bval *B
- Arrval *StrSlice
-}
-
-//gojay:json
-type B struct {
- Str string
- Bool bool
- Int int
- Int64 int64
- Int32 int32
- Int16 int16
- Int8 int8
- Uint64 uint64
- Uint32 uint32
- Uint16 uint16
- Uint8 uint8
- StrPtr *string
- BoolPtr *bool
- IntPtr *int
- Int64Ptr *int64
- Int32Ptr *int32
- Int16Ptr *int16
- Int8Ptr *int8
- Uint64Ptr *uint64
- Uint32Ptr *uint32
- Uint16Ptr *uint16
- Uint8PTr *uint8
-}
diff --git a/gojay/vendor/github.com/fatih/structtag/.travis.yml b/gojay/vendor/github.com/fatih/structtag/.travis.yml
@@ -1,4 +0,0 @@
-language: go
-go:
- - 1.7.x
- - tip
diff --git a/gojay/vendor/github.com/fatih/structtag/LICENSE b/gojay/vendor/github.com/fatih/structtag/LICENSE
@@ -1,60 +0,0 @@
-Copyright (c) 2017, Fatih Arslan
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of structtag nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-This software includes some portions from Go. Go is used under the terms of the
-BSD like license.
-
-Copyright (c) 2012 The Go Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-The Go gopher was designed by Renee French. http://reneefrench.blogspot.com/ The design is licensed under the Creative Commons 3.0 Attributions license. Read this article for more details: https://blog.golang.org/gopher
diff --git a/gojay/vendor/github.com/fatih/structtag/README.md b/gojay/vendor/github.com/fatih/structtag/README.md
@@ -1,73 +0,0 @@
-# structtag [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/fatih/structtag) [![Build Status](https://travis-ci.org/fatih/structtag.svg?branch=master)](https://travis-ci.org/fatih/structtag)
-
-structtag provides an easy way of parsing and manipulating struct tag fields.
-Please vendor the library as it might change in future versions.
-
-# Install
-
-```bash
-go get github.com/fatih/structtag
-```
-
-# Example
-
-```go
-package main
-
-import (
- "fmt"
- "reflect"
- "sort"
-
- "github.com/fatih/structtag"
-)
-
-func main() {
- type t struct {
- t string `json:"foo,omitempty,string" xml:"foo"`
- }
-
- // get field tag
- tag := reflect.TypeOf(t{}).Field(0).Tag
-
- // ... and start using structtag by parsing the tag
- tags, err := structtag.Parse(string(tag))
- if err != nil {
- panic(err)
- }
-
- // iterate over all tags
- for _, t := range tags.Tags() {
- fmt.Printf("tag: %+v\n", t)
- }
-
- // get a single tag
- jsonTag, err := tags.Get("json")
- if err != nil {
- panic(err)
- }
- fmt.Println(jsonTag) // Output: json:"foo,omitempty,string"
- fmt.Println(jsonTag.Key) // Output: json
- fmt.Println(jsonTag.Name) // Output: foo
- fmt.Println(jsonTag.Options) // Output: [omitempty string]
-
- // change existing tag
- jsonTag.Name = "foo_bar"
- jsonTag.Options = nil
- tags.Set(jsonTag)
-
- // add new tag
- tags.Set(&structtag.Tag{
- Key: "hcl",
- Name: "foo",
- Options: []string{"squash"},
- })
-
- // print the tags
- fmt.Println(tags) // Output: json:"foo_bar" xml:"foo" hcl:"foo,squash"
-
- // sort tags according to keys
- sort.Sort(tags)
- fmt.Println(tags) // Output: hcl:"foo,squash" json:"foo_bar" xml:"foo"
-}
-```
diff --git a/gojay/vendor/github.com/fatih/structtag/tags.go b/gojay/vendor/github.com/fatih/structtag/tags.go
@@ -1,303 +0,0 @@
-package structtag
-
-import (
- "bytes"
- "errors"
- "fmt"
- "strconv"
- "strings"
-)
-
-var (
- errTagSyntax = errors.New("bad syntax for struct tag pair")
- errTagKeySyntax = errors.New("bad syntax for struct tag key")
- errTagValueSyntax = errors.New("bad syntax for struct tag value")
-
- errKeyNotSet = errors.New("tag key does not exist")
- errTagNotExist = errors.New("tag does not exist")
- errTagKeyMismatch = errors.New("mismatch between key and tag.key")
-)
-
-// Tags represent a set of tags from a single struct field
-type Tags struct {
- tags []*Tag
-}
-
-// Tag defines a single struct's string literal tag
-type Tag struct {
- // Key is the tag key, such as json, xml, etc..
- // i.e: `json:"foo,omitempty". Here key is: "json"
- Key string
-
- // Name is a part of the value
- // i.e: `json:"foo,omitempty". Here name is: "foo"
- Name string
-
- // Options is a part of the value. It contains a slice of tag options i.e:
- // `json:"foo,omitempty". Here options is: ["omitempty"]
- Options []string
-}
-
-// Parse parses a single struct field tag and returns the set of tags.
-func Parse(tag string) (*Tags, error) {
- var tags []*Tag
-
- // NOTE(arslan) following code is from reflect and vet package with some
- // modifications to collect all necessary information and extend it with
- // usable methods
- for tag != "" {
- // Skip leading space.
- i := 0
- for i < len(tag) && tag[i] == ' ' {
- i++
- }
- tag = tag[i:]
- if tag == "" {
- return nil, nil
- }
-
- // Scan to colon. A space, a quote or a control character is a syntax
- // error. Strictly speaking, control chars include the range [0x7f,
- // 0x9f], not just [0x00, 0x1f], but in practice, we ignore the
- // multi-byte control characters as it is simpler to inspect the tag's
- // bytes than the tag's runes.
- i = 0
- for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
- i++
- }
-
- if i == 0 {
- return nil, errTagKeySyntax
- }
- if i+1 >= len(tag) || tag[i] != ':' {
- return nil, errTagSyntax
- }
- if tag[i+1] != '"' {
- return nil, errTagValueSyntax
- }
-
- key := string(tag[:i])
- tag = tag[i+1:]
-
- // Scan quoted string to find value.
- i = 1
- for i < len(tag) && tag[i] != '"' {
- if tag[i] == '\\' {
- i++
- }
- i++
- }
- if i >= len(tag) {
- return nil, errTagValueSyntax
- }
-
- qvalue := string(tag[:i+1])
- tag = tag[i+1:]
-
- value, err := strconv.Unquote(qvalue)
- if err != nil {
- return nil, errTagValueSyntax
- }
-
- res := strings.Split(value, ",")
- name := res[0]
- options := res[1:]
- if len(options) == 0 {
- options = nil
- }
-
- tags = append(tags, &Tag{
- Key: key,
- Name: name,
- Options: options,
- })
- }
-
- return &Tags{
- tags: tags,
- }, nil
-}
-
-// Get returns the tag associated with the given key. If the key is present
-// in the tag the value (which may be empty) is returned. Otherwise the
-// returned value will be the empty string. The ok return value reports whether
-// the tag exists or not (which the return value is nil).
-func (t *Tags) Get(key string) (*Tag, error) {
- for _, tag := range t.tags {
- if tag.Key == key {
- return tag, nil
- }
- }
-
- return nil, errTagNotExist
-}
-
-// Set sets the given tag. If the tag key already exists it'll override it
-func (t *Tags) Set(tag *Tag) error {
- if tag.Key == "" {
- return errKeyNotSet
- }
-
- added := false
- for i, tg := range t.tags {
- if tg.Key == tag.Key {
- added = true
- t.tags[i] = tag
- }
- }
-
- if !added {
- // this means this is a new tag, add it
- t.tags = append(t.tags, tag)
- }
-
- return nil
-}
-
-// AddOptions adds the given option for the given key. If the option already
-// exists it doesn't add it again.
-func (t *Tags) AddOptions(key string, options ...string) {
- for i, tag := range t.tags {
- if tag.Key != key {
- continue
- }
-
- for _, opt := range options {
- if !tag.HasOption(opt) {
- tag.Options = append(tag.Options, opt)
- }
- }
-
- t.tags[i] = tag
- }
-}
-
-// DeleteOptions deletes the given options for the given key
-func (t *Tags) DeleteOptions(key string, options ...string) {
- hasOption := func(option string) bool {
- for _, opt := range options {
- if opt == option {
- return true
- }
- }
- return false
- }
-
- for i, tag := range t.tags {
- if tag.Key != key {
- continue
- }
-
- var updated []string
- for _, opt := range tag.Options {
- if !hasOption(opt) {
- updated = append(updated, opt)
- }
- }
-
- tag.Options = updated
- t.tags[i] = tag
- }
-}
-
-// Delete deletes the tag for the given keys
-func (t *Tags) Delete(keys ...string) {
- hasKey := func(key string) bool {
- for _, k := range keys {
- if k == key {
- return true
- }
- }
- return false
- }
-
- var updated []*Tag
- for _, tag := range t.tags {
- if !hasKey(tag.Key) {
- updated = append(updated, tag)
- }
- }
-
- t.tags = updated
-}
-
-// Tags returns a slice of tags. The order is the original tag order unless it
-// was changed.
-func (t *Tags) Tags() []*Tag {
- return t.tags
-}
-
-// Tags returns a slice of tags. The order is the original tag order unless it
-// was changed.
-func (t *Tags) Keys() []string {
- var keys []string
- for _, tag := range t.tags {
- keys = append(keys, tag.Key)
- }
- return keys
-}
-
-// String reassembles the tags into a valid literal tag field representation
-func (t *Tags) String() string {
- tags := t.Tags()
- if len(tags) == 0 {
- return ""
- }
-
- var buf bytes.Buffer
- for i, tag := range t.Tags() {
- buf.WriteString(tag.String())
- if i != len(tags)-1 {
- buf.WriteString(" ")
- }
- }
- return buf.String()
-}
-
-// HasOption returns true if the given option is available in options
-func (t *Tag) HasOption(opt string) bool {
- for _, tagOpt := range t.Options {
- if tagOpt == opt {
- return true
- }
- }
-
- return false
-}
-
-// String reassembles the tag into a valid tag field representation
-func (t *Tag) String() string {
- options := strings.Join(t.Options, ",")
- if options != "" {
- return fmt.Sprintf(`%s:"%s,%s"`, t.Key, t.Name, options)
- }
- return fmt.Sprintf(`%s:"%s"`, t.Key, t.Name)
-}
-
-// GoString implements the fmt.GoStringer interface
-func (t *Tag) GoString() string {
- template := `{
- Key: '%s',
- Name: '%s',
- Option: '%s',
- }`
-
- if t.Options == nil {
- return fmt.Sprintf(template, t.Key, t.Name, "nil")
- }
-
- options := strings.Join(t.Options, ",")
- return fmt.Sprintf(template, t.Key, t.Name, options)
-}
-
-func (t *Tags) Len() int {
- return len(t.tags)
-}
-
-func (t *Tags) Less(i int, j int) bool {
- return t.tags[i].Key < t.tags[j].Key
-}
-
-func (t *Tags) Swap(i int, j int) {
- t.tags[i], t.tags[j] = t.tags[j], t.tags[i]
-}
diff --git a/gojay/vendor/github.com/fatih/structtag/tags_test.go b/gojay/vendor/github.com/fatih/structtag/tags_test.go
@@ -1,390 +0,0 @@
-package structtag
-
-import (
- "reflect"
- "sort"
- "testing"
-)
-
-func TestParse(t *testing.T) {
- test := []struct {
- name string
- tag string
- exp []*Tag
- invalid bool
- }{
- {
- name: "empty tag",
- tag: "",
- },
- {
- name: "tag with one key (invalid)",
- tag: "json",
- invalid: true,
- },
- {
- name: "tag with one key (valid)",
- tag: `json:""`,
- exp: []*Tag{
- {
- Key: "json",
- },
- },
- },
- {
- name: "tag with one key and dash name",
- tag: `json:"-"`,
- exp: []*Tag{
- {
- Key: "json",
- Name: "-",
- },
- },
- },
- {
- name: "tag with key and name",
- tag: `json:"foo"`,
- exp: []*Tag{
- {
- Key: "json",
- Name: "foo",
- },
- },
- },
- {
- name: "tag with key, name and option",
- tag: `json:"foo,omitempty"`,
- exp: []*Tag{
- {
- Key: "json",
- Name: "foo",
- Options: []string{"omitempty"},
- },
- },
- },
- {
- name: "tag with multiple keys",
- tag: `json:"" hcl:""`,
- exp: []*Tag{
- {
- Key: "json",
- },
- {
- Key: "hcl",
- },
- },
- },
- {
- name: "tag with multiple keys and names",
- tag: `json:"foo" hcl:"foo"`,
- exp: []*Tag{
- {
- Key: "json",
- Name: "foo",
- },
- {
- Key: "hcl",
- Name: "foo",
- },
- },
- },
- {
- name: "tag with multiple keys and names",
- tag: `json:"foo" hcl:"foo"`,
- exp: []*Tag{
- {
- Key: "json",
- Name: "foo",
- },
- {
- Key: "hcl",
- Name: "foo",
- },
- },
- },
- {
- name: "tag with multiple keys and different names",
- tag: `json:"foo" hcl:"bar"`,
- exp: []*Tag{
- {
- Key: "json",
- Name: "foo",
- },
- {
- Key: "hcl",
- Name: "bar",
- },
- },
- },
- {
- name: "tag with multiple keys, different names and options",
- tag: `json:"foo,omitempty" structs:"bar,omitnested"`,
- exp: []*Tag{
- {
- Key: "json",
- Name: "foo",
- Options: []string{"omitempty"},
- },
- {
- Key: "structs",
- Name: "bar",
- Options: []string{"omitnested"},
- },
- },
- },
- {
- name: "tag with multiple keys, different names and options",
- tag: `json:"foo" structs:"bar,omitnested" hcl:"-"`,
- exp: []*Tag{
- {
- Key: "json",
- Name: "foo",
- },
- {
- Key: "structs",
- Name: "bar",
- Options: []string{"omitnested"},
- },
- {
- Key: "hcl",
- Name: "-",
- },
- },
- },
- }
-
- for _, ts := range test {
- t.Run(ts.name, func(t *testing.T) {
- tags, err := Parse(ts.tag)
- invalid := err != nil
-
- if invalid != ts.invalid {
- t.Errorf("invalid case\n\twant: %+v\n\tgot : %+v\n\terr : %s", ts.invalid, invalid, err)
- }
-
- if invalid {
- return
- }
-
- got := tags.Tags()
-
- if !reflect.DeepEqual(ts.exp, got) {
- t.Errorf("parse\n\twant: %#v\n\tgot : %#v", ts.exp, got)
- }
- })
- }
-}
-
-func TestTags_Get(t *testing.T) {
- tag := `json:"foo,omitempty" structs:"bar,omitnested"`
-
- tags, err := Parse(tag)
- if err != nil {
- t.Fatal(err)
- }
-
- found, err := tags.Get("json")
- if err != nil {
- t.Fatal(err)
- }
-
- want := `json:"foo,omitempty"`
-
- if found.String() != want {
- t.Errorf("get\n\twant: %#v\n\tgot : %#v", want, found.String())
- }
-}
-
-func TestTags_Set(t *testing.T) {
- tag := `json:"foo,omitempty" structs:"bar,omitnested"`
-
- tags, err := Parse(tag)
- if err != nil {
- t.Fatal(err)
- }
-
- err = tags.Set(&Tag{
- Key: "json",
- Name: "bar",
- Options: []string{},
- })
- if err != nil {
- t.Fatal(err)
- }
-
- found, err := tags.Get("json")
- if err != nil {
- t.Fatal(err)
- }
-
- want := `json:"bar"`
- if found.String() != want {
- t.Errorf("set\n\twant: %#v\n\tgot : %#v", want, found.String())
- }
-}
-
-func TestTags_Set_Append(t *testing.T) {
- tag := `json:"foo,omitempty"`
-
- tags, err := Parse(tag)
- if err != nil {
- t.Fatal(err)
- }
-
- err = tags.Set(&Tag{
- Key: "structs",
- Name: "bar",
- Options: []string{"omitnested"},
- })
- if err != nil {
- t.Fatal(err)
- }
-
- found, err := tags.Get("structs")
- if err != nil {
- t.Fatal(err)
- }
-
- want := `structs:"bar,omitnested"`
- if found.String() != want {
- t.Errorf("set append\n\twant: %#v\n\tgot : %#v", want, found.String())
- }
-
- wantFull := `json:"foo,omitempty" structs:"bar,omitnested"`
- if tags.String() != wantFull {
- t.Errorf("set append\n\twant: %#v\n\tgot : %#v", wantFull, tags.String())
- }
-}
-
-func TestTags_Set_KeyDoesNotExist(t *testing.T) {
- tag := `json:"foo,omitempty" structs:"bar,omitnested"`
-
- tags, err := Parse(tag)
- if err != nil {
- t.Fatal(err)
- }
-
- err = tags.Set(&Tag{
- Key: "",
- Name: "bar",
- Options: []string{},
- })
- if err == nil {
- t.Fatal("setting tag with a nonexisting key should error")
- }
-
- if err != errKeyNotSet {
- t.Errorf("set\n\twant: %#v\n\tgot : %#v", errTagKeyMismatch, err)
- }
-}
-
-func TestTags_Delete(t *testing.T) {
- tag := `json:"foo,omitempty" structs:"bar,omitnested" hcl:"-"`
-
- tags, err := Parse(tag)
- if err != nil {
- t.Fatal(err)
- }
-
- tags.Delete("structs")
- if tags.Len() != 2 {
- t.Fatalf("tag length should be 2, have %d", tags.Len())
- }
-
- found, err := tags.Get("json")
- if err != nil {
- t.Fatal(err)
- }
-
- want := `json:"foo,omitempty"`
- if found.String() != want {
- t.Errorf("delete\n\twant: %#v\n\tgot : %#v", want, found.String())
- }
-
- wantFull := `json:"foo,omitempty" hcl:"-"`
- if tags.String() != wantFull {
- t.Errorf("delete\n\twant: %#v\n\tgot : %#v", wantFull, tags.String())
- }
-}
-
-func TestTags_DeleteOptions(t *testing.T) {
- tag := `json:"foo,omitempty" structs:"bar,omitnested,omitempty" hcl:"-"`
-
- tags, err := Parse(tag)
- if err != nil {
- t.Fatal(err)
- }
-
- tags.DeleteOptions("json", "omitempty")
-
- want := `json:"foo" structs:"bar,omitnested,omitempty" hcl:"-"`
- if tags.String() != want {
- t.Errorf("delete option\n\twant: %#v\n\tgot : %#v", want, tags.String())
- }
-
- tags.DeleteOptions("structs", "omitnested")
- want = `json:"foo" structs:"bar,omitempty" hcl:"-"`
- if tags.String() != want {
- t.Errorf("delete option\n\twant: %#v\n\tgot : %#v", want, tags.String())
- }
-}
-
-func TestTags_AddOption(t *testing.T) {
- tag := `json:"foo" structs:"bar,omitempty" hcl:"-"`
-
- tags, err := Parse(tag)
- if err != nil {
- t.Fatal(err)
- }
-
- tags.AddOptions("json", "omitempty")
-
- want := `json:"foo,omitempty" structs:"bar,omitempty" hcl:"-"`
- if tags.String() != want {
- t.Errorf("add options\n\twant: %#v\n\tgot : %#v", want, tags.String())
- }
-
- // this shouldn't change anything
- tags.AddOptions("structs", "omitempty")
-
- want = `json:"foo,omitempty" structs:"bar,omitempty" hcl:"-"`
- if tags.String() != want {
- t.Errorf("add options\n\twant: %#v\n\tgot : %#v", want, tags.String())
- }
-
- // this should append to the existing
- tags.AddOptions("structs", "omitnested", "flatten")
- want = `json:"foo,omitempty" structs:"bar,omitempty,omitnested,flatten" hcl:"-"`
- if tags.String() != want {
- t.Errorf("add options\n\twant: %#v\n\tgot : %#v", want, tags.String())
- }
-}
-
-func TestTags_String(t *testing.T) {
- tag := `json:"foo" structs:"bar,omitnested" hcl:"-"`
-
- tags, err := Parse(tag)
- if err != nil {
- t.Fatal(err)
- }
-
- if tags.String() != tag {
- t.Errorf("string\n\twant: %#v\n\tgot : %#v", tag, tags.String())
- }
-}
-
-func TestTags_Sort(t *testing.T) {
- tag := `json:"foo" structs:"bar,omitnested" hcl:"-"`
-
- tags, err := Parse(tag)
- if err != nil {
- t.Fatal(err)
- }
-
- sort.Sort(tags)
-
- want := `hcl:"-" json:"foo" structs:"bar,omitnested"`
- if tags.String() != want {
- t.Errorf("string\n\twant: %#v\n\tgot : %#v", want, tags.String())
- }
-}
diff --git a/gojay/visitor.go b/gojay/visitor.go
@@ -1,54 +0,0 @@
-package main
-
-import (
- "go/ast"
- "strings"
-)
-
-func docContains(n *ast.CommentGroup, s string) bool {
- for _, d := range n.List {
- if strings.Contains(d.Text, s) {
- return true
- }
- }
- return false
-}
-
-type vis struct {
- pkg string
- g *Gen
- commentFound bool
-}
-
-func (v *vis) Visit(n ast.Node) (w ast.Visitor) {
- switch n := n.(type) {
- case *ast.Package:
- v.commentFound = false
- return v
- case *ast.File:
- v.commentFound = false
- return v
- case *ast.GenDecl:
- if len(v.g.types) == 0 && n.Doc != nil {
- v.commentFound = docContains(n.Doc, gojayAnnotation)
- }
- return v
- case *ast.TypeSpec:
- if v.commentFound || v.g.isGenType(n.Name.Name) {
- v.g.genTypes[n.Name.Name] = n
- }
- v.commentFound = false
- return v
- case *ast.StructType:
- v.commentFound = false
- return v
- }
- return v
-}
-
-func newVisitor(g *Gen, pkgName string) *vis {
- return &vis{
- g: g,
- pkg: pkgName,
- }
-}
diff --git a/gojaygen/gojaygen.go b/gojaygen/gojaygen.go
@@ -1,22 +0,0 @@
-package main
-
-import (
- "flag"
- "github.com/francoispqt/gojay/codegen"
- "log"
-)
-
-var dst = flag.String("o", "", "destination file to output generated implementations")
-var src = flag.String("s", "", "source dir or file (absolute or relative path)")
-var types = flag.String("t", "", "types to generate")
-var annotation = flag.String("a", "json", "annotation tagg")
-var poolObjects = flag.String("p", "", "generate code to reuse objects")
-
-func main() {
- flag.Parse()
- options := codegen.NewOptionsWithFlagSet(flag.CommandLine)
- gen := &codegen.Generator{}
- if err := gen.Generate(options); err != nil {
- log.Fatal(err)
- }
-}