2016-02-28 03:16:29 +03:00
package gen
import (
2017-03-06 21:23:53 +03:00
"encoding"
2016-03-04 23:27:56 +10:00
"encoding/json"
2020-04-12 21:22:21 +03:00
"errors"
2016-02-28 03:16:29 +03:00
"fmt"
"reflect"
"strings"
"unicode"
"github.com/mailru/easyjson"
)
// Target this byte size for initial slice allocation to reduce garbage collection.
const minSliceBytes = 64
2016-07-15 17:46:25 +03:00
func ( g * Generator ) getDecoderName ( t reflect . Type ) string {
2016-06-08 18:08:55 +03:00
return g . functionName ( "decode" , t )
2016-02-28 03:16:29 +03:00
}
var primitiveDecoders = map [ reflect . Kind ] string {
reflect . String : "in.String()" ,
reflect . Bool : "in.Bool()" ,
reflect . Int : "in.Int()" ,
reflect . Int8 : "in.Int8()" ,
reflect . Int16 : "in.Int16()" ,
reflect . Int32 : "in.Int32()" ,
reflect . Int64 : "in.Int64()" ,
reflect . Uint : "in.Uint()" ,
reflect . Uint8 : "in.Uint8()" ,
reflect . Uint16 : "in.Uint16()" ,
reflect . Uint32 : "in.Uint32()" ,
reflect . Uint64 : "in.Uint64()" ,
reflect . Float32 : "in.Float32()" ,
reflect . Float64 : "in.Float64()" ,
}
2016-04-18 15:40:08 +03:00
var primitiveStringDecoders = map [ reflect . Kind ] string {
2017-10-19 19:06:37 -07:00
reflect . String : "in.String()" ,
reflect . Int : "in.IntStr()" ,
reflect . Int8 : "in.Int8Str()" ,
reflect . Int16 : "in.Int16Str()" ,
reflect . Int32 : "in.Int32Str()" ,
reflect . Int64 : "in.Int64Str()" ,
reflect . Uint : "in.UintStr()" ,
reflect . Uint8 : "in.Uint8Str()" ,
reflect . Uint16 : "in.Uint16Str()" ,
reflect . Uint32 : "in.Uint32Str()" ,
reflect . Uint64 : "in.Uint64Str()" ,
reflect . Uintptr : "in.UintptrStr()" ,
2017-11-26 18:55:54 -05:00
reflect . Float32 : "in.Float32Str()" ,
reflect . Float64 : "in.Float64Str()" ,
2016-04-18 15:40:08 +03:00
}
2017-10-18 00:11:05 +03:00
var customDecoders = map [ string ] string {
2017-11-22 21:11:58 +03:00
"json.Number" : "in.JsonNumber()" ,
2017-10-18 00:11:05 +03:00
}
2016-07-18 15:58:29 +03:00
// genTypeDecoder generates decoding code for the type t, but uses unmarshaler interface if implemented by t.
2016-04-18 15:40:08 +03:00
func ( g * Generator ) genTypeDecoder ( t reflect . Type , out string , tags fieldTags , indent int ) error {
2016-02-28 03:16:29 +03:00
ws := strings . Repeat ( " " , indent )
unmarshalerIface := reflect . TypeOf ( ( * easyjson . Unmarshaler ) ( nil ) ) . Elem ( )
if reflect . PtrTo ( t ) . Implements ( unmarshalerIface ) {
2025-01-09 11:27:28 -08:00
fmt . Fprintln ( g . out , ws + "if in.IsNull() {" )
fmt . Fprintln ( g . out , ws + " in.Skip()" )
fmt . Fprintln ( g . out , ws + "} else {" )
fmt . Fprintln ( g . out , ws + " (" + out + ").UnmarshalEasyJSON(in)" )
fmt . Fprintln ( g . out , ws + "}" )
2016-02-28 03:16:29 +03:00
return nil
}
2016-03-04 23:27:56 +10:00
unmarshalerIface = reflect . TypeOf ( ( * json . Unmarshaler ) ( nil ) ) . Elem ( )
if reflect . PtrTo ( t ) . Implements ( unmarshalerIface ) {
2025-01-09 11:27:28 -08:00
fmt . Fprintln ( g . out , ws + "if in.IsNull() {" )
fmt . Fprintln ( g . out , ws + " in.Skip()" )
fmt . Fprintln ( g . out , ws + "} else {" )
fmt . Fprintln ( g . out , ws + " if data := in.Raw(); in.Ok() {" )
fmt . Fprintln ( g . out , ws + " in.AddError( (" + out + ").UnmarshalJSON(data) )" )
fmt . Fprintln ( g . out , ws + " }" )
2016-03-04 23:27:56 +10:00
fmt . Fprintln ( g . out , ws + "}" )
return nil
}
2017-03-06 21:23:53 +03:00
unmarshalerIface = reflect . TypeOf ( ( * encoding . TextUnmarshaler ) ( nil ) ) . Elem ( )
if reflect . PtrTo ( t ) . Implements ( unmarshalerIface ) {
2025-01-09 11:27:28 -08:00
fmt . Fprintln ( g . out , ws + "if in.IsNull() {" )
fmt . Fprintln ( g . out , ws + " in.Skip()" )
fmt . Fprintln ( g . out , ws + "} else {" )
fmt . Fprintln ( g . out , ws + " if data := in.UnsafeBytes(); in.Ok() {" )
fmt . Fprintln ( g . out , ws + " in.AddError( (" + out + ").UnmarshalText(data) )" )
fmt . Fprintln ( g . out , ws + " }" )
2017-03-06 21:23:53 +03:00
fmt . Fprintln ( g . out , ws + "}" )
return nil
}
2016-07-15 17:46:25 +03:00
err := g . genTypeDecoderNoCheck ( t , out , tags , indent )
return err
}
2019-03-23 12:19:38 +03:00
// returns true if the type t implements one of the custom unmarshaler interfaces
2018-03-06 13:29:46 -08:00
func hasCustomUnmarshaler ( t reflect . Type ) bool {
t = reflect . PtrTo ( t )
return t . Implements ( reflect . TypeOf ( ( * easyjson . Unmarshaler ) ( nil ) ) . Elem ( ) ) ||
t . Implements ( reflect . TypeOf ( ( * json . Unmarshaler ) ( nil ) ) . Elem ( ) ) ||
t . Implements ( reflect . TypeOf ( ( * encoding . TextUnmarshaler ) ( nil ) ) . Elem ( ) )
}
2020-02-17 15:02:51 +03:00
func hasUnknownsUnmarshaler ( t reflect . Type ) bool {
t = reflect . PtrTo ( t )
return t . Implements ( reflect . TypeOf ( ( * easyjson . UnknownsUnmarshaler ) ( nil ) ) . Elem ( ) )
}
func hasUnknownsMarshaler ( t reflect . Type ) bool {
t = reflect . PtrTo ( t )
return t . Implements ( reflect . TypeOf ( ( * easyjson . UnknownsMarshaler ) ( nil ) ) . Elem ( ) )
}
2016-07-15 17:46:25 +03:00
// genTypeDecoderNoCheck generates decoding code for the type t.
func ( g * Generator ) genTypeDecoderNoCheck ( t reflect . Type , out string , tags fieldTags , indent int ) error {
ws := strings . Repeat ( " " , indent )
2016-02-28 03:16:29 +03:00
// Check whether type is primitive, needs to be done after interface check.
2017-11-22 21:11:58 +03:00
if dec := customDecoders [ t . String ( ) ] ; dec != "" {
2025-01-09 11:27:28 -08:00
fmt . Fprintln ( g . out , ws + "if in.IsNull() {" )
fmt . Fprintln ( g . out , ws + " in.Skip()" )
fmt . Fprintln ( g . out , ws + "} else {" )
fmt . Fprintln ( g . out , ws + " " + out + " = " + dec )
fmt . Fprintln ( g . out , ws + "}" )
2017-10-18 00:11:05 +03:00
return nil
} else if dec := primitiveStringDecoders [ t . Kind ( ) ] ; dec != "" && tags . asString {
2020-04-07 11:02:46 +09:00
if tags . intern && t . Kind ( ) == reflect . String {
dec = "in.StringIntern()"
}
2025-01-09 11:27:28 -08:00
fmt . Fprintln ( g . out , ws + "if in.IsNull() {" )
fmt . Fprintln ( g . out , ws + " in.Skip()" )
fmt . Fprintln ( g . out , ws + "} else {" )
fmt . Fprintln ( g . out , ws + " " + out + " = " + g . getType ( t ) + "(" + dec + ")" )
fmt . Fprintln ( g . out , ws + "}" )
2016-04-18 15:40:08 +03:00
return nil
} else if dec := primitiveDecoders [ t . Kind ( ) ] ; dec != "" {
2020-04-07 11:02:46 +09:00
if tags . intern && t . Kind ( ) == reflect . String {
dec = "in.StringIntern()"
}
2020-04-11 20:48:34 +03:00
if tags . noCopy && t . Kind ( ) == reflect . String {
dec = "in.UnsafeString()"
}
2025-01-09 11:27:28 -08:00
fmt . Fprintln ( g . out , ws + "if in.IsNull() {" )
fmt . Fprintln ( g . out , ws + " in.Skip()" )
fmt . Fprintln ( g . out , ws + "} else {" )
fmt . Fprintln ( g . out , ws + " " + out + " = " + g . getType ( t ) + "(" + dec + ")" )
fmt . Fprintln ( g . out , ws + "}" )
2016-02-28 03:16:29 +03:00
return nil
}
switch t . Kind ( ) {
case reflect . Slice :
tmpVar := g . uniqueVarName ( )
elem := t . Elem ( )
2018-04-27 01:46:49 +03:00
if elem . Kind ( ) == reflect . Uint8 && elem . Name ( ) == "uint8" {
2016-08-18 13:23:52 -07:00
fmt . Fprintln ( g . out , ws + "if in.IsNull() {" )
fmt . Fprintln ( g . out , ws + " in.Skip()" )
fmt . Fprintln ( g . out , ws + " " + out + " = nil" )
fmt . Fprintln ( g . out , ws + "} else {" )
2017-11-22 21:11:58 +03:00
if g . simpleBytes {
fmt . Fprintln ( g . out , ws + " " + out + " = []byte(in.String())" )
} else {
fmt . Fprintln ( g . out , ws + " " + out + " = in.Bytes()" )
}
2016-08-18 13:23:52 -07:00
fmt . Fprintln ( g . out , ws + "}" )
} else {
2019-08-08 13:08:02 +03:00
capacity := 1
if elem . Size ( ) > 0 {
capacity = minSliceBytes / int ( elem . Size ( ) )
2016-08-18 13:23:52 -07:00
}
fmt . Fprintln ( g . out , ws + "if in.IsNull() {" )
fmt . Fprintln ( g . out , ws + " in.Skip()" )
fmt . Fprintln ( g . out , ws + " " + out + " = nil" )
fmt . Fprintln ( g . out , ws + "} else {" )
fmt . Fprintln ( g . out , ws + " in.Delim('[')" )
2017-01-31 17:02:53 +08:00
fmt . Fprintln ( g . out , ws + " if " + out + " == nil {" )
fmt . Fprintln ( g . out , ws + " if !in.IsDelim(']') {" )
fmt . Fprintln ( g . out , ws + " " + out + " = make(" + g . getType ( t ) + ", 0, " + fmt . Sprint ( capacity ) + ")" )
fmt . Fprintln ( g . out , ws + " } else {" )
fmt . Fprintln ( g . out , ws + " " + out + " = " + g . getType ( t ) + "{}" )
fmt . Fprintln ( g . out , ws + " }" )
fmt . Fprintln ( g . out , ws + " } else { " )
fmt . Fprintln ( g . out , ws + " " + out + " = (" + out + ")[:0]" )
2016-08-18 13:23:52 -07:00
fmt . Fprintln ( g . out , ws + " }" )
fmt . Fprintln ( g . out , ws + " for !in.IsDelim(']') {" )
fmt . Fprintln ( g . out , ws + " var " + tmpVar + " " + g . getType ( elem ) )
2020-04-15 00:45:56 +03:00
if err := g . genTypeDecoder ( elem , tmpVar , tags , indent + 2 ) ; err != nil {
2017-10-16 18:33:24 -07:00
return err
}
2016-08-18 13:23:52 -07:00
fmt . Fprintln ( g . out , ws + " " + out + " = append(" + out + ", " + tmpVar + ")" )
fmt . Fprintln ( g . out , ws + " in.WantComma()" )
fmt . Fprintln ( g . out , ws + " }" )
fmt . Fprintln ( g . out , ws + " in.Delim(']')" )
fmt . Fprintln ( g . out , ws + "}" )
2016-02-28 03:16:29 +03:00
}
2016-09-22 01:13:38 -07:00
case reflect . Array :
iterVar := g . uniqueVarName ( )
elem := t . Elem ( )
2018-04-27 01:46:49 +03:00
if elem . Kind ( ) == reflect . Uint8 && elem . Name ( ) == "uint8" {
2016-09-22 01:13:38 -07:00
fmt . Fprintln ( g . out , ws + "if in.IsNull() {" )
fmt . Fprintln ( g . out , ws + " in.Skip()" )
fmt . Fprintln ( g . out , ws + "} else {" )
fmt . Fprintln ( g . out , ws + " copy(" + out + "[:], in.Bytes())" )
fmt . Fprintln ( g . out , ws + "}" )
} else {
length := t . Len ( )
fmt . Fprintln ( g . out , ws + "if in.IsNull() {" )
fmt . Fprintln ( g . out , ws + " in.Skip()" )
fmt . Fprintln ( g . out , ws + "} else {" )
fmt . Fprintln ( g . out , ws + " in.Delim('[')" )
fmt . Fprintln ( g . out , ws + " " + iterVar + " := 0" )
2016-09-23 16:53:34 -07:00
fmt . Fprintln ( g . out , ws + " for !in.IsDelim(']') {" )
fmt . Fprintln ( g . out , ws + " if " + iterVar + " < " + fmt . Sprint ( length ) + " {" )
2016-09-22 01:13:38 -07:00
2020-04-15 00:45:56 +03:00
if err := g . genTypeDecoder ( elem , "(" + out + ")[" + iterVar + "]" , tags , indent + 3 ) ; err != nil {
2017-10-16 18:33:24 -07:00
return err
}
2016-09-22 01:13:38 -07:00
2016-09-23 16:53:34 -07:00
fmt . Fprintln ( g . out , ws + " " + iterVar + "++" )
fmt . Fprintln ( g . out , ws + " } else {" )
fmt . Fprintln ( g . out , ws + " in.SkipRecursive()" )
fmt . Fprintln ( g . out , ws + " }" )
2016-09-22 01:13:38 -07:00
fmt . Fprintln ( g . out , ws + " in.WantComma()" )
fmt . Fprintln ( g . out , ws + " }" )
fmt . Fprintln ( g . out , ws + " in.Delim(']')" )
fmt . Fprintln ( g . out , ws + "}" )
}
2016-02-28 03:16:29 +03:00
case reflect . Struct :
2016-07-15 17:46:25 +03:00
dec := g . getDecoderName ( t )
2016-02-28 03:16:29 +03:00
g . addType ( t )
2019-02-20 21:52:23 +00:00
if len ( out ) > 0 && out [ 0 ] == '*' {
// NOTE: In order to remove an extra reference to a pointer
fmt . Fprintln ( g . out , ws + dec + "(in, " + out [ 1 : ] + ")" )
} else {
fmt . Fprintln ( g . out , ws + dec + "(in, &" + out + ")" )
}
2016-02-28 03:16:29 +03:00
case reflect . Ptr :
fmt . Fprintln ( g . out , ws + "if in.IsNull() {" )
fmt . Fprintln ( g . out , ws + " in.Skip()" )
fmt . Fprintln ( g . out , ws + " " + out + " = nil" )
fmt . Fprintln ( g . out , ws + "} else {" )
2016-08-18 13:23:33 -07:00
fmt . Fprintln ( g . out , ws + " if " + out + " == nil {" )
2016-08-09 15:15:11 -07:00
fmt . Fprintln ( g . out , ws + " " + out + " = new(" + g . getType ( t . Elem ( ) ) + ")" )
fmt . Fprintln ( g . out , ws + " }" )
2016-02-28 03:16:29 +03:00
2020-04-15 00:45:56 +03:00
if err := g . genTypeDecoder ( t . Elem ( ) , "*" + out , tags , indent + 1 ) ; err != nil {
2017-10-16 18:33:24 -07:00
return err
}
2016-02-28 03:16:29 +03:00
fmt . Fprintln ( g . out , ws + "}" )
case reflect . Map :
key := t . Key ( )
2017-10-19 19:06:37 -07:00
keyDec , ok := primitiveStringDecoders [ key . Kind ( ) ]
2018-03-06 13:29:46 -08:00
if ! ok && ! hasCustomUnmarshaler ( key ) {
return fmt . Errorf ( "map type %v not supported: only string and integer keys and types implementing json.Unmarshaler are allowed" , key )
} // else assume the caller knows what they are doing and that the custom unmarshaler performs the translation from string or integer keys to the key type
2016-02-28 03:16:29 +03:00
elem := t . Elem ( )
tmpVar := g . uniqueVarName ( )
2019-11-21 18:03:16 -08:00
keepEmpty := tags . required || tags . noOmitEmpty || ( ! g . omitEmpty && ! tags . omitEmpty )
2016-02-28 03:16:29 +03:00
2016-04-12 14:10:37 +03:00
fmt . Fprintln ( g . out , ws + "if in.IsNull() {" )
fmt . Fprintln ( g . out , ws + " in.Skip()" )
2016-02-28 03:16:29 +03:00
fmt . Fprintln ( g . out , ws + "} else {" )
2016-04-12 14:10:37 +03:00
fmt . Fprintln ( g . out , ws + " in.Delim('{')" )
2019-11-21 18:03:16 -08:00
if ! keepEmpty {
fmt . Fprintln ( g . out , ws + " if !in.IsDelim('}') {" )
}
2016-07-15 17:46:25 +03:00
fmt . Fprintln ( g . out , ws + " " + out + " = make(" + g . getType ( t ) + ")" )
2019-11-21 18:03:16 -08:00
if ! keepEmpty {
fmt . Fprintln ( g . out , ws + " } else {" )
fmt . Fprintln ( g . out , ws + " " + out + " = nil" )
fmt . Fprintln ( g . out , ws + " }" )
}
2016-04-12 14:10:37 +03:00
fmt . Fprintln ( g . out , ws + " for !in.IsDelim('}') {" )
2019-04-03 16:25:01 +00:00
// NOTE: extra check for TextUnmarshaler. It overrides default methods.
if reflect . PtrTo ( key ) . Implements ( reflect . TypeOf ( ( * encoding . TextUnmarshaler ) ( nil ) ) . Elem ( ) ) {
fmt . Fprintln ( g . out , ws + " var key " + g . getType ( key ) )
fmt . Fprintln ( g . out , ws + "if data := in.UnsafeBytes(); in.Ok() {" )
fmt . Fprintln ( g . out , ws + " in.AddError(key.UnmarshalText(data) )" )
fmt . Fprintln ( g . out , ws + "}" )
} else if keyDec != "" {
2018-03-06 13:29:46 -08:00
fmt . Fprintln ( g . out , ws + " key := " + g . getType ( key ) + "(" + keyDec + ")" )
} else {
fmt . Fprintln ( g . out , ws + " var key " + g . getType ( key ) )
2020-04-15 00:45:56 +03:00
if err := g . genTypeDecoder ( key , "key" , tags , indent + 2 ) ; err != nil {
2018-03-06 13:29:46 -08:00
return err
}
}
2016-04-12 14:10:37 +03:00
fmt . Fprintln ( g . out , ws + " in.WantColon()" )
fmt . Fprintln ( g . out , ws + " var " + tmpVar + " " + g . getType ( elem ) )
2020-04-15 00:45:56 +03:00
if err := g . genTypeDecoder ( elem , tmpVar , tags , indent + 2 ) ; err != nil {
2017-10-16 18:33:24 -07:00
return err
}
2016-04-12 14:10:37 +03:00
fmt . Fprintln ( g . out , ws + " (" + out + ")[key] = " + tmpVar )
fmt . Fprintln ( g . out , ws + " in.WantComma()" )
fmt . Fprintln ( g . out , ws + " }" )
fmt . Fprintln ( g . out , ws + " in.Delim('}')" )
2016-02-28 03:16:29 +03:00
fmt . Fprintln ( g . out , ws + "}" )
case reflect . Interface :
if t . NumMethod ( ) != 0 {
2019-01-23 19:53:03 +03:00
if g . interfaceIsEasyjsonUnmarshaller ( t ) {
fmt . Fprintln ( g . out , ws + out + ".UnmarshalEasyJSON(in)" )
} else if g . interfaceIsJsonUnmarshaller ( t ) {
fmt . Fprintln ( g . out , ws + out + ".UnmarshalJSON(in.Raw())" )
} else {
return fmt . Errorf ( "interface type %v not supported: only interface{} and easyjson/json Unmarshaler are allowed" , t )
}
2019-03-23 12:19:38 +03:00
} else {
fmt . Fprintln ( g . out , ws + "if m, ok := " + out + ".(easyjson.Unmarshaler); ok {" )
fmt . Fprintln ( g . out , ws + "m.UnmarshalEasyJSON(in)" )
fmt . Fprintln ( g . out , ws + "} else if m, ok := " + out + ".(json.Unmarshaler); ok {" )
fmt . Fprintln ( g . out , ws + "_ = m.UnmarshalJSON(in.Raw())" )
fmt . Fprintln ( g . out , ws + "} else {" )
fmt . Fprintln ( g . out , ws + " " + out + " = in.Interface()" )
fmt . Fprintln ( g . out , ws + "}" )
2016-02-28 03:16:29 +03:00
}
default :
return fmt . Errorf ( "don't know how to decode %v" , t )
}
return nil
}
2019-01-23 19:53:03 +03:00
func ( g * Generator ) interfaceIsEasyjsonUnmarshaller ( t reflect . Type ) bool {
2019-03-23 12:19:38 +03:00
return t . Implements ( reflect . TypeOf ( ( * easyjson . Unmarshaler ) ( nil ) ) . Elem ( ) )
2019-01-23 19:53:03 +03:00
}
func ( g * Generator ) interfaceIsJsonUnmarshaller ( t reflect . Type ) bool {
2019-03-23 12:19:38 +03:00
return t . Implements ( reflect . TypeOf ( ( * json . Unmarshaler ) ( nil ) ) . Elem ( ) )
2019-01-23 19:53:03 +03:00
}
2016-02-28 03:16:29 +03:00
func ( g * Generator ) genStructFieldDecoder ( t reflect . Type , f reflect . StructField ) error {
2016-06-08 18:08:55 +03:00
jsonName := g . fieldNamer . GetJSONFieldName ( t , f )
2016-04-18 15:40:08 +03:00
tags := parseFieldTags ( f )
2016-02-28 03:16:29 +03:00
2016-05-10 13:52:19 +03:00
if tags . omit {
return nil
}
2020-04-12 21:22:21 +03:00
if tags . intern && tags . noCopy {
return errors . New ( "Mutually exclusive tags are specified: 'intern' and 'nocopy'" )
}
2016-05-10 13:52:19 +03:00
2016-02-28 03:16:29 +03:00
fmt . Fprintf ( g . out , " case %q:\n" , jsonName )
2016-05-15 23:02:01 +03:00
if err := g . genTypeDecoder ( f . Type , "out." + f . Name , tags , 3 ) ; err != nil {
return err
}
if tags . required {
2016-05-16 11:06:41 +03:00
fmt . Fprintf ( g . out , "%sSet = true\n" , f . Name )
2016-05-15 23:02:01 +03:00
}
return nil
}
2016-05-16 11:06:41 +03:00
func ( g * Generator ) genRequiredFieldSet ( t reflect . Type , f reflect . StructField ) {
2016-05-15 23:02:01 +03:00
tags := parseFieldTags ( f )
if ! tags . required {
2016-05-16 11:06:41 +03:00
return
2016-05-15 23:02:01 +03:00
}
2016-05-16 11:06:41 +03:00
fmt . Fprintf ( g . out , "var %sSet bool\n" , f . Name )
2016-05-15 23:02:01 +03:00
}
2016-05-16 11:06:41 +03:00
func ( g * Generator ) genRequiredFieldCheck ( t reflect . Type , f reflect . StructField ) {
2016-06-08 18:08:55 +03:00
jsonName := g . fieldNamer . GetJSONFieldName ( t , f )
2016-05-15 23:02:01 +03:00
tags := parseFieldTags ( f )
if ! tags . required {
2016-05-16 11:06:41 +03:00
return
2016-05-15 23:02:01 +03:00
}
g . imports [ "fmt" ] = "fmt"
2016-05-16 11:06:41 +03:00
fmt . Fprintf ( g . out , "if !%sSet {\n" , f . Name )
2016-05-15 23:02:01 +03:00
fmt . Fprintf ( g . out , " in.AddError(fmt.Errorf(\"key '%s' is required\"))\n" , jsonName )
fmt . Fprintf ( g . out , "}\n" )
2016-02-28 03:16:29 +03:00
}
func mergeStructFields ( fields1 , fields2 [ ] reflect . StructField ) ( fields [ ] reflect . StructField ) {
used := map [ string ] bool { }
for _ , f := range fields2 {
used [ f . Name ] = true
fields = append ( fields , f )
}
for _ , f := range fields1 {
if ! used [ f . Name ] {
fields = append ( fields , f )
}
}
return
}
2016-04-05 02:00:33 +03:00
func getStructFields ( t reflect . Type ) ( [ ] reflect . StructField , error ) {
if t . Kind ( ) != reflect . Struct {
return nil , fmt . Errorf ( "got %v; expected a struct" , t )
}
2016-02-28 03:16:29 +03:00
var efields [ ] reflect . StructField
2019-02-02 21:55:42 +02:00
var fields [ ] reflect . StructField
2016-02-28 03:16:29 +03:00
for i := 0 ; i < t . NumField ( ) ; i ++ {
f := t . Field ( i )
2019-01-10 18:43:09 +00:00
tags := parseFieldTags ( f )
if ! f . Anonymous || tags . name != "" {
2016-02-28 03:16:29 +03:00
continue
}
2016-04-05 02:00:33 +03:00
t1 := f . Type
if t1 . Kind ( ) == reflect . Ptr {
t1 = t1 . Elem ( )
}
2019-02-02 21:55:42 +02:00
if t1 . Kind ( ) == reflect . Struct {
fs , err := getStructFields ( t1 )
if err != nil {
return nil , fmt . Errorf ( "error processing embedded field: %v" , err )
}
efields = mergeStructFields ( efields , fs )
2019-02-02 22:06:25 +02:00
} else if ( t1 . Kind ( ) >= reflect . Bool && t1 . Kind ( ) < reflect . Complex128 ) || t1 . Kind ( ) == reflect . String {
2019-02-02 21:55:42 +02:00
if strings . Contains ( f . Name , "." ) || unicode . IsUpper ( [ ] rune ( f . Name ) [ 0 ] ) {
fields = append ( fields , f )
}
2016-04-05 02:00:33 +03:00
}
2016-02-28 03:16:29 +03:00
}
for i := 0 ; i < t . NumField ( ) ; i ++ {
f := t . Field ( i )
2019-01-10 18:43:09 +00:00
tags := parseFieldTags ( f )
if f . Anonymous && tags . name == "" {
2016-02-28 03:16:29 +03:00
continue
}
c := [ ] rune ( f . Name ) [ 0 ]
if unicode . IsUpper ( c ) {
fields = append ( fields , f )
}
}
2016-04-05 02:00:33 +03:00
return mergeStructFields ( efields , fields ) , nil
2016-02-28 03:16:29 +03:00
}
2016-07-18 15:04:06 +03:00
func ( g * Generator ) genDecoder ( t reflect . Type ) error {
switch t . Kind ( ) {
2016-10-07 15:52:17 +03:00
case reflect . Slice , reflect . Array , reflect . Map :
2016-09-22 01:13:38 -07:00
return g . genSliceArrayDecoder ( t )
2016-07-18 15:04:06 +03:00
default :
return g . genStructDecoder ( t )
}
}
2016-09-22 01:13:38 -07:00
func ( g * Generator ) genSliceArrayDecoder ( t reflect . Type ) error {
2016-10-07 15:52:17 +03:00
switch t . Kind ( ) {
case reflect . Slice , reflect . Array , reflect . Map :
default :
return fmt . Errorf ( "cannot generate encoder/decoder for %v, not a slice/array/map type" , t )
2016-02-28 03:16:29 +03:00
}
2016-07-15 17:46:25 +03:00
fname := g . getDecoderName ( t )
typ := g . getType ( t )
fmt . Fprintln ( g . out , "func " + fname + "(in *jlexer.Lexer, out *" + typ + ") {" )
2016-10-30 21:20:44 -07:00
fmt . Fprintln ( g . out , " isTopLevel := in.IsStart()" )
2016-07-18 16:20:51 +03:00
err := g . genTypeDecoderNoCheck ( t , "*out" , fieldTags { } , 1 )
2016-07-15 17:46:25 +03:00
if err != nil {
return err
}
2016-10-30 21:20:44 -07:00
fmt . Fprintln ( g . out , " if isTopLevel {" )
fmt . Fprintln ( g . out , " in.Consumed()" )
fmt . Fprintln ( g . out , " }" )
2016-07-15 17:46:25 +03:00
fmt . Fprintln ( g . out , "}" )
return nil
}
2016-02-28 03:16:29 +03:00
func ( g * Generator ) genStructDecoder ( t reflect . Type ) error {
if t . Kind ( ) != reflect . Struct {
return fmt . Errorf ( "cannot generate encoder/decoder for %v, not a struct type" , t )
}
2016-07-15 17:46:25 +03:00
fname := g . getDecoderName ( t )
2016-02-28 03:16:29 +03:00
typ := g . getType ( t )
fmt . Fprintln ( g . out , "func " + fname + "(in *jlexer.Lexer, out *" + typ + ") {" )
2016-10-30 21:20:44 -07:00
fmt . Fprintln ( g . out , " isTopLevel := in.IsStart()" )
2016-04-13 16:17:22 +03:00
fmt . Fprintln ( g . out , " if in.IsNull() {" )
2016-10-30 21:20:44 -07:00
fmt . Fprintln ( g . out , " if isTopLevel {" )
fmt . Fprintln ( g . out , " in.Consumed()" )
fmt . Fprintln ( g . out , " }" )
2016-04-13 16:17:22 +03:00
fmt . Fprintln ( g . out , " in.Skip()" )
fmt . Fprintln ( g . out , " return" )
fmt . Fprintln ( g . out , " }" )
2016-04-05 02:00:33 +03:00
// Init embedded pointer fields.
for i := 0 ; i < t . NumField ( ) ; i ++ {
f := t . Field ( i )
if ! f . Anonymous || f . Type . Kind ( ) != reflect . Ptr {
continue
}
fmt . Fprintln ( g . out , " out." + f . Name + " = new(" + g . getType ( f . Type . Elem ( ) ) + ")" )
}
2016-05-15 23:02:01 +03:00
fs , err := getStructFields ( t )
if err != nil {
return fmt . Errorf ( "cannot generate decoder for %v: %v" , t , err )
}
for _ , f := range fs {
2016-05-16 11:06:41 +03:00
g . genRequiredFieldSet ( t , f )
2016-05-15 23:02:01 +03:00
}
2016-02-28 03:16:29 +03:00
fmt . Fprintln ( g . out , " in.Delim('{')" )
fmt . Fprintln ( g . out , " for !in.IsDelim('}') {" )
2020-04-11 20:20:50 +03:00
fmt . Fprintf ( g . out , " key := in.UnsafeFieldName(%v)\n" , g . skipMemberNameUnescaping )
2016-02-28 03:16:29 +03:00
fmt . Fprintln ( g . out , " in.WantColon()" )
2016-05-15 23:02:01 +03:00
2016-02-28 03:16:29 +03:00
fmt . Fprintln ( g . out , " switch key {" )
2016-04-05 02:00:33 +03:00
for _ , f := range fs {
2016-02-28 03:16:29 +03:00
if err := g . genStructFieldDecoder ( t , f ) ; err != nil {
return err
}
}
fmt . Fprintln ( g . out , " default:" )
2018-05-29 16:19:21 +00:00
if g . disallowUnknownFields {
fmt . Fprintln ( g . out , ` in.AddError(&jlexer.LexerError {
Offset: in.GetPos(),
Reason: "unknown field",
Data: key,
}) ` )
2020-02-17 15:02:51 +03:00
} else if hasUnknownsUnmarshaler ( t ) {
fmt . Fprintln ( g . out , " out.UnmarshalUnknown(in, key)" )
2018-05-29 16:19:21 +00:00
} else {
fmt . Fprintln ( g . out , " in.SkipRecursive()" )
}
2016-02-28 03:16:29 +03:00
fmt . Fprintln ( g . out , " }" )
fmt . Fprintln ( g . out , " in.WantComma()" )
fmt . Fprintln ( g . out , " }" )
fmt . Fprintln ( g . out , " in.Delim('}')" )
2016-10-30 21:20:44 -07:00
fmt . Fprintln ( g . out , " if isTopLevel {" )
fmt . Fprintln ( g . out , " in.Consumed()" )
fmt . Fprintln ( g . out , " }" )
2016-05-15 23:02:01 +03:00
for _ , f := range fs {
2016-05-16 11:06:41 +03:00
g . genRequiredFieldCheck ( t , f )
2016-05-15 23:02:01 +03:00
}
2016-02-28 03:16:29 +03:00
fmt . Fprintln ( g . out , "}" )
return nil
}
2016-12-19 21:02:38 +07:00
func ( g * Generator ) genStructUnmarshaler ( t reflect . Type ) error {
2016-10-07 15:52:17 +03:00
switch t . Kind ( ) {
case reflect . Slice , reflect . Array , reflect . Map , reflect . Struct :
default :
return fmt . Errorf ( "cannot generate encoder/decoder for %v, not a struct/slice/array/map type" , t )
2016-02-28 03:16:29 +03:00
}
2016-07-15 17:46:25 +03:00
fname := g . getDecoderName ( t )
2016-02-28 03:16:29 +03:00
typ := g . getType ( t )
2016-03-04 23:27:56 +10:00
if ! g . noStdMarshalers {
2016-06-08 18:08:55 +03:00
fmt . Fprintln ( g . out , "// UnmarshalJSON supports json.Unmarshaler interface" )
2016-03-04 23:27:56 +10:00
fmt . Fprintln ( g . out , "func (v *" + typ + ") UnmarshalJSON(data []byte) error {" )
fmt . Fprintln ( g . out , " r := jlexer.Lexer{Data: data}" )
fmt . Fprintln ( g . out , " " + fname + "(&r, v)" )
fmt . Fprintln ( g . out , " return r.Error()" )
fmt . Fprintln ( g . out , "}" )
}
2016-06-08 18:08:55 +03:00
fmt . Fprintln ( g . out , "// UnmarshalEasyJSON supports easyjson.Unmarshaler interface" )
2016-02-28 03:16:29 +03:00
fmt . Fprintln ( g . out , "func (v *" + typ + ") UnmarshalEasyJSON(l *jlexer.Lexer) {" )
fmt . Fprintln ( g . out , " " + fname + "(l, v)" )
fmt . Fprintln ( g . out , "}" )
return nil
}