|
@@ -101,7 +101,7 @@ import (
|
|
|
// v4: Removed separator support from (en|de)cDriver, and refactored codec(gen)
|
|
// v4: Removed separator support from (en|de)cDriver, and refactored codec(gen)
|
|
|
// v5: changes to support faster json decoding. Let encoder/decoder maintain state of collections.
|
|
// v5: changes to support faster json decoding. Let encoder/decoder maintain state of collections.
|
|
|
// v6: removed unsafe from gen, and now uses codecgen.exec tag
|
|
// v6: removed unsafe from gen, and now uses codecgen.exec tag
|
|
|
-const genVersion = 6
|
|
|
|
|
|
|
+const genVersion = 8
|
|
|
|
|
|
|
|
const (
|
|
const (
|
|
|
genCodecPkg = "codec1978"
|
|
genCodecPkg = "codec1978"
|
|
@@ -163,13 +163,16 @@ type genRunner struct {
|
|
|
|
|
|
|
|
ti *TypeInfos
|
|
ti *TypeInfos
|
|
|
// rr *rand.Rand // random generator for file-specific types
|
|
// rr *rand.Rand // random generator for file-specific types
|
|
|
|
|
+
|
|
|
|
|
+ nx bool // no extensions
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Gen will write a complete go file containing Selfer implementations for each
|
|
// Gen will write a complete go file containing Selfer implementations for each
|
|
|
// type passed. All the types must be in the same package.
|
|
// type passed. All the types must be in the same package.
|
|
|
//
|
|
//
|
|
|
// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
|
|
// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
|
|
|
-func Gen(w io.Writer, buildTags, pkgName, uid string, ti *TypeInfos, typ ...reflect.Type) {
|
|
|
|
|
|
|
+func Gen(w io.Writer, buildTags, pkgName, uid string, noExtensions bool,
|
|
|
|
|
+ ti *TypeInfos, typ ...reflect.Type) {
|
|
|
// All types passed to this method do not have a codec.Selfer method implemented directly.
|
|
// All types passed to this method do not have a codec.Selfer method implemented directly.
|
|
|
// codecgen already checks the AST and skips any types that define the codec.Selfer methods.
|
|
// codecgen already checks the AST and skips any types that define the codec.Selfer methods.
|
|
|
// Consequently, there's no need to check and trim them if they implement codec.Selfer
|
|
// Consequently, there's no need to check and trim them if they implement codec.Selfer
|
|
@@ -190,6 +193,7 @@ func Gen(w io.Writer, buildTags, pkgName, uid string, ti *TypeInfos, typ ...refl
|
|
|
bp: genImportPath(typ[0]),
|
|
bp: genImportPath(typ[0]),
|
|
|
xs: uid,
|
|
xs: uid,
|
|
|
ti: ti,
|
|
ti: ti,
|
|
|
|
|
+ nx: noExtensions,
|
|
|
}
|
|
}
|
|
|
if x.ti == nil {
|
|
if x.ti == nil {
|
|
|
x.ti = defTypeInfos
|
|
x.ti = defTypeInfos
|
|
@@ -713,7 +717,7 @@ func (x *genRunner) enc(varname string, t reflect.Type) {
|
|
|
x.linef("r.EncodeBuiltin(%s, %s)", vrtid, varname)
|
|
x.linef("r.EncodeBuiltin(%s, %s)", vrtid, varname)
|
|
|
}
|
|
}
|
|
|
// only check for extensions if the type is named, and has a packagePath.
|
|
// only check for extensions if the type is named, and has a packagePath.
|
|
|
- if genImportPath(t) != "" && t.Name() != "" {
|
|
|
|
|
|
|
+ if !x.nx && genImportPath(t) != "" && t.Name() != "" {
|
|
|
// first check if extensions are configued, before doing the interface conversion
|
|
// first check if extensions are configued, before doing the interface conversion
|
|
|
x.linef("} else if z.HasExtensions() && z.EncExt(%s) {", varname)
|
|
x.linef("} else if z.HasExtensions() && z.EncExt(%s) {", varname)
|
|
|
}
|
|
}
|
|
@@ -773,7 +777,7 @@ func (x *genRunner) enc(varname string, t reflect.Type) {
|
|
|
x.line("r.EncodeStringBytes(codecSelferC_RAW" + x.xs + ", []byte(" + varname + "))")
|
|
x.line("r.EncodeStringBytes(codecSelferC_RAW" + x.xs + ", []byte(" + varname + "))")
|
|
|
} else if fastpathAV.index(rtid) != -1 {
|
|
} else if fastpathAV.index(rtid) != -1 {
|
|
|
g := x.newGenV(t)
|
|
g := x.newGenV(t)
|
|
|
- x.line("z.F." + g.MethodNamePfx("Enc", false) + "V(" + varname + ", false, e)")
|
|
|
|
|
|
|
+ x.line("z.F." + g.MethodNamePfx("Enc", false) + "V(" + varname + ", e)")
|
|
|
} else {
|
|
} else {
|
|
|
x.xtraSM(varname, true, t)
|
|
x.xtraSM(varname, true, t)
|
|
|
// x.encListFallback(varname, rtid, t)
|
|
// x.encListFallback(varname, rtid, t)
|
|
@@ -787,7 +791,7 @@ func (x *genRunner) enc(varname string, t reflect.Type) {
|
|
|
// x.line("if " + varname + " == nil { \nr.EncodeNil()\n } else { ")
|
|
// x.line("if " + varname + " == nil { \nr.EncodeNil()\n } else { ")
|
|
|
if fastpathAV.index(rtid) != -1 {
|
|
if fastpathAV.index(rtid) != -1 {
|
|
|
g := x.newGenV(t)
|
|
g := x.newGenV(t)
|
|
|
- x.line("z.F." + g.MethodNamePfx("Enc", false) + "V(" + varname + ", false, e)")
|
|
|
|
|
|
|
+ x.line("z.F." + g.MethodNamePfx("Enc", false) + "V(" + varname + ", e)")
|
|
|
} else {
|
|
} else {
|
|
|
x.xtraSM(varname, true, t)
|
|
x.xtraSM(varname, true, t)
|
|
|
// x.encMapFallback(varname, rtid, t)
|
|
// x.encMapFallback(varname, rtid, t)
|
|
@@ -845,55 +849,64 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
|
|
|
// number of non-empty things we write out first.
|
|
// number of non-empty things we write out first.
|
|
|
// This is required as we need to pre-determine the size of the container,
|
|
// This is required as we need to pre-determine the size of the container,
|
|
|
// to support length-prefixing.
|
|
// to support length-prefixing.
|
|
|
- x.linef("var %s [%v]bool", numfieldsvar, len(tisfi))
|
|
|
|
|
- x.linef("_, _, _ = %s, %s, %s", sepVarname, numfieldsvar, struct2arrvar)
|
|
|
|
|
|
|
+ if ti.anyOmitEmpty {
|
|
|
|
|
+ x.linef("var %s [%v]bool", numfieldsvar, len(tisfi))
|
|
|
|
|
+ x.linef("_ = %s", numfieldsvar)
|
|
|
|
|
+ }
|
|
|
|
|
+ x.linef("_, _ = %s, %s", sepVarname, struct2arrvar)
|
|
|
x.linef("const %s bool = %v", ti2arrayvar, ti.toArray)
|
|
x.linef("const %s bool = %v", ti2arrayvar, ti.toArray)
|
|
|
- nn := 0
|
|
|
|
|
- for j, si := range tisfi {
|
|
|
|
|
- if !si.omitEmpty {
|
|
|
|
|
- nn++
|
|
|
|
|
- continue
|
|
|
|
|
- }
|
|
|
|
|
- var t2 reflect.StructField
|
|
|
|
|
- var omitline string
|
|
|
|
|
- if si.i != -1 {
|
|
|
|
|
- t2 = t.Field(int(si.i))
|
|
|
|
|
- } else {
|
|
|
|
|
- t2typ := t
|
|
|
|
|
- varname3 := varname
|
|
|
|
|
- for _, ix := range si.is {
|
|
|
|
|
- for t2typ.Kind() == reflect.Ptr {
|
|
|
|
|
- t2typ = t2typ.Elem()
|
|
|
|
|
- }
|
|
|
|
|
- t2 = t2typ.Field(ix)
|
|
|
|
|
- t2typ = t2.Type
|
|
|
|
|
- varname3 = varname3 + "." + t2.Name
|
|
|
|
|
- if t2typ.Kind() == reflect.Ptr {
|
|
|
|
|
- omitline += varname3 + " != nil && "
|
|
|
|
|
|
|
+ var nn int
|
|
|
|
|
+ if ti.anyOmitEmpty {
|
|
|
|
|
+ for j, si := range tisfi {
|
|
|
|
|
+ if !si.omitEmpty {
|
|
|
|
|
+ nn++
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+ var t2 reflect.StructField
|
|
|
|
|
+ var omitline string
|
|
|
|
|
+ {
|
|
|
|
|
+ t2typ := t
|
|
|
|
|
+ varname3 := varname
|
|
|
|
|
+ for ij, ix := range si.is {
|
|
|
|
|
+ if uint8(ij) == si.nis {
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ for t2typ.Kind() == reflect.Ptr {
|
|
|
|
|
+ t2typ = t2typ.Elem()
|
|
|
|
|
+ }
|
|
|
|
|
+ t2 = t2typ.Field(int(ix))
|
|
|
|
|
+ t2typ = t2.Type
|
|
|
|
|
+ varname3 = varname3 + "." + t2.Name
|
|
|
|
|
+ if t2typ.Kind() == reflect.Ptr {
|
|
|
|
|
+ omitline += varname3 + " != nil && "
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ // never check omitEmpty on a struct type, as it may contain uncomparable map/slice/etc.
|
|
|
|
|
+ // also, for maps/slices/arrays, check if len ! 0 (not if == zero value)
|
|
|
|
|
+ switch t2.Type.Kind() {
|
|
|
|
|
+ case reflect.Struct:
|
|
|
|
|
+ omitline += " true"
|
|
|
|
|
+ case reflect.Map, reflect.Slice, reflect.Array, reflect.Chan:
|
|
|
|
|
+ omitline += "len(" + varname + "." + t2.Name + ") != 0"
|
|
|
|
|
+ default:
|
|
|
|
|
+ omitline += varname + "." + t2.Name + " != " + x.genZeroValueR(t2.Type)
|
|
|
|
|
+ }
|
|
|
|
|
+ x.linef("%s[%v] = %s", numfieldsvar, j, omitline)
|
|
|
}
|
|
}
|
|
|
- // never check omitEmpty on a struct type, as it may contain uncomparable map/slice/etc.
|
|
|
|
|
- // also, for maps/slices/arrays, check if len ! 0 (not if == zero value)
|
|
|
|
|
- switch t2.Type.Kind() {
|
|
|
|
|
- case reflect.Struct:
|
|
|
|
|
- omitline += " true"
|
|
|
|
|
- case reflect.Map, reflect.Slice, reflect.Array, reflect.Chan:
|
|
|
|
|
- omitline += "len(" + varname + "." + t2.Name + ") != 0"
|
|
|
|
|
- default:
|
|
|
|
|
- omitline += varname + "." + t2.Name + " != " + x.genZeroValueR(t2.Type)
|
|
|
|
|
- }
|
|
|
|
|
- x.linef("%s[%v] = %s", numfieldsvar, j, omitline)
|
|
|
|
|
}
|
|
}
|
|
|
- x.linef("var %snn%s int", genTempVarPfx, i)
|
|
|
|
|
|
|
+ // x.linef("var %snn%s int", genTempVarPfx, i)
|
|
|
x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray {
|
|
x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray {
|
|
|
- x.line("r.EncodeArrayStart(" + strconv.FormatInt(int64(len(tisfi)), 10) + ")")
|
|
|
|
|
|
|
+ x.linef("r.WriteArrayStart(%d)", len(tisfi))
|
|
|
x.linef("} else {") // if not ti.toArray
|
|
x.linef("} else {") // if not ti.toArray
|
|
|
- x.linef("%snn%s = %v", genTempVarPfx, i, nn)
|
|
|
|
|
- x.linef("for _, b := range %s { if b { %snn%s++ } }", numfieldsvar, genTempVarPfx, i)
|
|
|
|
|
- x.linef("r.EncodeMapStart(%snn%s)", genTempVarPfx, i)
|
|
|
|
|
- x.linef("%snn%s = %v", genTempVarPfx, i, 0)
|
|
|
|
|
- // x.line("r.EncodeMapStart(" + strconv.FormatInt(int64(len(tisfi)), 10) + ")")
|
|
|
|
|
|
|
+ if ti.anyOmitEmpty {
|
|
|
|
|
+ x.linef("var %snn%s = %v", genTempVarPfx, i, nn)
|
|
|
|
|
+ x.linef("for _, b := range %s { if b { %snn%s++ } }", numfieldsvar, genTempVarPfx, i)
|
|
|
|
|
+ x.linef("r.WriteMapStart(%snn%s)", genTempVarPfx, i)
|
|
|
|
|
+ x.linef("%snn%s = %v", genTempVarPfx, i, 0)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ x.linef("r.WriteMapStart(%d)", len(tisfi))
|
|
|
|
|
+ }
|
|
|
x.line("}") // close if not StructToArray
|
|
x.line("}") // close if not StructToArray
|
|
|
|
|
|
|
|
for j, si := range tisfi {
|
|
for j, si := range tisfi {
|
|
@@ -901,17 +914,18 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
|
|
|
isNilVarName := genTempVarPfx + "n" + i
|
|
isNilVarName := genTempVarPfx + "n" + i
|
|
|
var labelUsed bool
|
|
var labelUsed bool
|
|
|
var t2 reflect.StructField
|
|
var t2 reflect.StructField
|
|
|
- if si.i != -1 {
|
|
|
|
|
- t2 = t.Field(int(si.i))
|
|
|
|
|
- } else {
|
|
|
|
|
|
|
+ {
|
|
|
t2typ := t
|
|
t2typ := t
|
|
|
varname3 := varname
|
|
varname3 := varname
|
|
|
- for _, ix := range si.is {
|
|
|
|
|
|
|
+ for ij, ix := range si.is {
|
|
|
|
|
+ if uint8(ij) == si.nis {
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
// fmt.Printf("%%%% %v, ix: %v\n", t2typ, ix)
|
|
// fmt.Printf("%%%% %v, ix: %v\n", t2typ, ix)
|
|
|
for t2typ.Kind() == reflect.Ptr {
|
|
for t2typ.Kind() == reflect.Ptr {
|
|
|
t2typ = t2typ.Elem()
|
|
t2typ = t2typ.Elem()
|
|
|
}
|
|
}
|
|
|
- t2 = t2typ.Field(ix)
|
|
|
|
|
|
|
+ t2 = t2typ.Field(int(ix))
|
|
|
t2typ = t2.Type
|
|
t2typ = t2.Type
|
|
|
varname3 = varname3 + "." + t2.Name
|
|
varname3 = varname3 + "." + t2.Name
|
|
|
if t2typ.Kind() == reflect.Ptr {
|
|
if t2typ.Kind() == reflect.Ptr {
|
|
@@ -934,9 +948,10 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
|
|
|
|
|
|
|
|
x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray
|
|
x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray
|
|
|
if labelUsed {
|
|
if labelUsed {
|
|
|
- x.line("if " + isNilVarName + " { r.EncodeNil() } else { ")
|
|
|
|
|
|
|
+ x.linef("if %s { r.WriteArrayElem(); r.EncodeNil() } else { ", isNilVarName)
|
|
|
|
|
+ // x.linef("if %s { z.EncSendContainerState(codecSelfer_containerArrayElem%s); r.EncodeNil() } else { ", isNilVarName, x.xs)
|
|
|
}
|
|
}
|
|
|
- x.linef("z.EncSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.WriteArrayElem()") // x.linef("z.EncSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
|
|
|
if si.omitEmpty {
|
|
if si.omitEmpty {
|
|
|
x.linef("if %s[%v] {", numfieldsvar, j)
|
|
x.linef("if %s[%v] {", numfieldsvar, j)
|
|
|
}
|
|
}
|
|
@@ -955,9 +970,9 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
|
|
|
if si.omitEmpty {
|
|
if si.omitEmpty {
|
|
|
x.linef("if %s[%v] {", numfieldsvar, j)
|
|
x.linef("if %s[%v] {", numfieldsvar, j)
|
|
|
}
|
|
}
|
|
|
- x.linef("z.EncSendContainerState(codecSelfer_containerMapKey%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.WriteMapElemKey()") // x.linef("z.EncSendContainerState(codecSelfer_containerMapKey%s)", x.xs)
|
|
|
x.line("r.EncodeString(codecSelferC_UTF8" + x.xs + ", string(\"" + si.encName + "\"))")
|
|
x.line("r.EncodeString(codecSelferC_UTF8" + x.xs + ", string(\"" + si.encName + "\"))")
|
|
|
- x.linef("z.EncSendContainerState(codecSelfer_containerMapValue%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.WriteMapElemValue()") // x.linef("z.EncSendContainerState(codecSelfer_containerMapValue%s)", x.xs)
|
|
|
if labelUsed {
|
|
if labelUsed {
|
|
|
x.line("if " + isNilVarName + " { r.EncodeNil() } else { ")
|
|
x.line("if " + isNilVarName + " { r.EncodeNil() } else { ")
|
|
|
x.encVar(varname+"."+t2.Name, t2.Type)
|
|
x.encVar(varname+"."+t2.Name, t2.Type)
|
|
@@ -971,9 +986,9 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
|
|
|
x.linef("} ") // end if/else ti.toArray
|
|
x.linef("} ") // end if/else ti.toArray
|
|
|
}
|
|
}
|
|
|
x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray {
|
|
x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray {
|
|
|
- x.linef("z.EncSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.WriteArrayEnd()") // x.linef("z.EncSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
|
|
|
x.line("} else {")
|
|
x.line("} else {")
|
|
|
- x.linef("z.EncSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.WriteMapEnd()") // x.linef("z.EncSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
|
|
|
x.line("}")
|
|
x.line("}")
|
|
|
|
|
|
|
|
}
|
|
}
|
|
@@ -989,36 +1004,36 @@ func (x *genRunner) encListFallback(varname string, t reflect.Type) {
|
|
|
}
|
|
}
|
|
|
i := x.varsfx()
|
|
i := x.varsfx()
|
|
|
g := genTempVarPfx
|
|
g := genTempVarPfx
|
|
|
- x.line("r.EncodeArrayStart(len(" + varname + "))")
|
|
|
|
|
|
|
+ x.line("r.WriteArrayStart(len(" + varname + "))")
|
|
|
if t.Kind() == reflect.Chan {
|
|
if t.Kind() == reflect.Chan {
|
|
|
x.linef("for %si%s, %si2%s := 0, len(%s); %si%s < %si2%s; %si%s++ {", g, i, g, i, varname, g, i, g, i, g, i)
|
|
x.linef("for %si%s, %si2%s := 0, len(%s); %si%s < %si2%s; %si%s++ {", g, i, g, i, varname, g, i, g, i, g, i)
|
|
|
- x.linef("z.EncSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.WriteArrayElem()") // x.linef("z.EncSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
|
|
|
x.linef("%sv%s := <-%s", g, i, varname)
|
|
x.linef("%sv%s := <-%s", g, i, varname)
|
|
|
} else {
|
|
} else {
|
|
|
// x.linef("for %si%s, %sv%s := range %s {", genTempVarPfx, i, genTempVarPfx, i, varname)
|
|
// x.linef("for %si%s, %sv%s := range %s {", genTempVarPfx, i, genTempVarPfx, i, varname)
|
|
|
x.linef("for _, %sv%s := range %s {", genTempVarPfx, i, varname)
|
|
x.linef("for _, %sv%s := range %s {", genTempVarPfx, i, varname)
|
|
|
- x.linef("z.EncSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.WriteArrayElem()") // x.linef("z.EncSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
|
|
|
}
|
|
}
|
|
|
x.encVar(genTempVarPfx+"v"+i, t.Elem())
|
|
x.encVar(genTempVarPfx+"v"+i, t.Elem())
|
|
|
x.line("}")
|
|
x.line("}")
|
|
|
- x.linef("z.EncSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.WriteArrayEnd()") // x.linef("z.EncSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (x *genRunner) encMapFallback(varname string, t reflect.Type) {
|
|
func (x *genRunner) encMapFallback(varname string, t reflect.Type) {
|
|
|
// TODO: expand this to handle canonical.
|
|
// TODO: expand this to handle canonical.
|
|
|
i := x.varsfx()
|
|
i := x.varsfx()
|
|
|
- x.line("r.EncodeMapStart(len(" + varname + "))")
|
|
|
|
|
|
|
+ x.line("r.WriteMapStart(len(" + varname + "))")
|
|
|
x.linef("for %sk%s, %sv%s := range %s {", genTempVarPfx, i, genTempVarPfx, i, varname)
|
|
x.linef("for %sk%s, %sv%s := range %s {", genTempVarPfx, i, genTempVarPfx, i, varname)
|
|
|
// x.line("for " + genTempVarPfx + "k" + i + ", " + genTempVarPfx + "v" + i + " := range " + varname + " {")
|
|
// x.line("for " + genTempVarPfx + "k" + i + ", " + genTempVarPfx + "v" + i + " := range " + varname + " {")
|
|
|
- x.linef("z.EncSendContainerState(codecSelfer_containerMapKey%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.WriteMapElemKey()") // f("z.EncSendContainerState(codecSelfer_containerMapKey%s)", x.xs)
|
|
|
x.encVar(genTempVarPfx+"k"+i, t.Key())
|
|
x.encVar(genTempVarPfx+"k"+i, t.Key())
|
|
|
- x.linef("z.EncSendContainerState(codecSelfer_containerMapValue%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.WriteMapElemValue()") // f("z.EncSendContainerState(codecSelfer_containerMapValue%s)", x.xs)
|
|
|
x.encVar(genTempVarPfx+"v"+i, t.Elem())
|
|
x.encVar(genTempVarPfx+"v"+i, t.Elem())
|
|
|
x.line("}")
|
|
x.line("}")
|
|
|
- x.linef("z.EncSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.WriteMapEnd()") // f("z.EncSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (x *genRunner) decVar(varname string, t reflect.Type, canBeNil bool) {
|
|
|
|
|
|
|
+func (x *genRunner) decVar(varname, decodedNilVarname string, t reflect.Type, canBeNil bool) {
|
|
|
// We only encode as nil if a nillable value.
|
|
// We only encode as nil if a nillable value.
|
|
|
// This removes some of the wasted checks for TryDecodeAsNil.
|
|
// This removes some of the wasted checks for TryDecodeAsNil.
|
|
|
// We need to think about this more, to see what happens if omitempty, etc
|
|
// We need to think about this more, to see what happens if omitempty, etc
|
|
@@ -1031,7 +1046,9 @@ func (x *genRunner) decVar(varname string, t reflect.Type, canBeNil bool) {
|
|
|
}
|
|
}
|
|
|
if canBeNil {
|
|
if canBeNil {
|
|
|
x.line("if r.TryDecodeAsNil() {")
|
|
x.line("if r.TryDecodeAsNil() {")
|
|
|
- if t.Kind() == reflect.Ptr {
|
|
|
|
|
|
|
+ if decodedNilVarname != "" {
|
|
|
|
|
+ x.line(decodedNilVarname + " = true")
|
|
|
|
|
+ } else if t.Kind() == reflect.Ptr {
|
|
|
x.line("if " + varname + " != nil { ")
|
|
x.line("if " + varname + " != nil { ")
|
|
|
|
|
|
|
|
// if varname is a field of a struct (has a dot in it),
|
|
// if varname is a field of a struct (has a dot in it),
|
|
@@ -1149,7 +1166,7 @@ func (x *genRunner) dec(varname string, t reflect.Type) {
|
|
|
x.linef("r.DecodeBuiltin(%s, %s)", vrtid, varname)
|
|
x.linef("r.DecodeBuiltin(%s, %s)", vrtid, varname)
|
|
|
}
|
|
}
|
|
|
// only check for extensions if the type is named, and has a packagePath.
|
|
// only check for extensions if the type is named, and has a packagePath.
|
|
|
- if genImportPath(t) != "" && t.Name() != "" {
|
|
|
|
|
|
|
+ if !x.nx && genImportPath(t) != "" && t.Name() != "" {
|
|
|
// first check if extensions are configued, before doing the interface conversion
|
|
// first check if extensions are configued, before doing the interface conversion
|
|
|
x.linef("} else if z.HasExtensions() && z.DecExt(%s) {", varname)
|
|
x.linef("} else if z.HasExtensions() && z.DecExt(%s) {", varname)
|
|
|
}
|
|
}
|
|
@@ -1227,7 +1244,7 @@ func (x *genRunner) dec(varname string, t reflect.Type) {
|
|
|
x.line("*" + varname + " = r.DecodeBytes(*(*[]byte)(" + varname + "), false)")
|
|
x.line("*" + varname + " = r.DecodeBytes(*(*[]byte)(" + varname + "), false)")
|
|
|
} else if fastpathAV.index(rtid) != -1 {
|
|
} else if fastpathAV.index(rtid) != -1 {
|
|
|
g := x.newGenV(t)
|
|
g := x.newGenV(t)
|
|
|
- x.line("z.F." + g.MethodNamePfx("Dec", false) + "X(" + varname + ", false, d)")
|
|
|
|
|
|
|
+ x.line("z.F." + g.MethodNamePfx("Dec", false) + "X(" + varname + ", d)")
|
|
|
} else {
|
|
} else {
|
|
|
x.xtraSM(varname, false, t)
|
|
x.xtraSM(varname, false, t)
|
|
|
// x.decListFallback(varname, rtid, false, t)
|
|
// x.decListFallback(varname, rtid, false, t)
|
|
@@ -1239,7 +1256,7 @@ func (x *genRunner) dec(varname string, t reflect.Type) {
|
|
|
// - else call Encoder.encode(XXX) on it.
|
|
// - else call Encoder.encode(XXX) on it.
|
|
|
if fastpathAV.index(rtid) != -1 {
|
|
if fastpathAV.index(rtid) != -1 {
|
|
|
g := x.newGenV(t)
|
|
g := x.newGenV(t)
|
|
|
- x.line("z.F." + g.MethodNamePfx("Dec", false) + "X(" + varname + ", false, d)")
|
|
|
|
|
|
|
+ x.line("z.F." + g.MethodNamePfx("Dec", false) + "X(" + varname + ", d)")
|
|
|
} else {
|
|
} else {
|
|
|
x.xtraSM(varname, false, t)
|
|
x.xtraSM(varname, false, t)
|
|
|
// x.decMapFallback(varname, rtid, t)
|
|
// x.decMapFallback(varname, rtid, t)
|
|
@@ -1333,13 +1350,13 @@ func (x *genRunner) decListFallback(varname string, rtid uintptr, t reflect.Type
|
|
|
funcs := make(template.FuncMap)
|
|
funcs := make(template.FuncMap)
|
|
|
|
|
|
|
|
funcs["decLineVar"] = func(varname string) string {
|
|
funcs["decLineVar"] = func(varname string) string {
|
|
|
- x.decVar(varname, telem, false)
|
|
|
|
|
- return ""
|
|
|
|
|
- }
|
|
|
|
|
- funcs["decLine"] = func(pfx string) string {
|
|
|
|
|
- x.decVar(ts.TempVar+pfx+ts.Rand, reflect.PtrTo(telem), false)
|
|
|
|
|
|
|
+ x.decVar(varname, "", telem, false)
|
|
|
return ""
|
|
return ""
|
|
|
}
|
|
}
|
|
|
|
|
+ // funcs["decLine"] = func(pfx string) string {
|
|
|
|
|
+ // x.decVar(ts.TempVar+pfx+ts.Rand, "", reflect.PtrTo(telem), false)
|
|
|
|
|
+ // return ""
|
|
|
|
|
+ // }
|
|
|
funcs["var"] = func(s string) string {
|
|
funcs["var"] = func(s string) string {
|
|
|
return ts.TempVar + s + ts.Rand
|
|
return ts.TempVar + s + ts.Rand
|
|
|
}
|
|
}
|
|
@@ -1395,21 +1412,21 @@ func (x *genRunner) decMapFallback(varname string, rtid uintptr, t reflect.Type)
|
|
|
return telem.Kind() == reflect.Interface
|
|
return telem.Kind() == reflect.Interface
|
|
|
}
|
|
}
|
|
|
funcs["decLineVarK"] = func(varname string) string {
|
|
funcs["decLineVarK"] = func(varname string) string {
|
|
|
- x.decVar(varname, tkey, false)
|
|
|
|
|
|
|
+ x.decVar(varname, "", tkey, false)
|
|
|
return ""
|
|
return ""
|
|
|
}
|
|
}
|
|
|
- funcs["decLineVar"] = func(varname string) string {
|
|
|
|
|
- x.decVar(varname, telem, false)
|
|
|
|
|
- return ""
|
|
|
|
|
- }
|
|
|
|
|
- funcs["decLineK"] = func(pfx string) string {
|
|
|
|
|
- x.decVar(ts.TempVar+pfx+ts.Rand, reflect.PtrTo(tkey), false)
|
|
|
|
|
- return ""
|
|
|
|
|
- }
|
|
|
|
|
- funcs["decLine"] = func(pfx string) string {
|
|
|
|
|
- x.decVar(ts.TempVar+pfx+ts.Rand, reflect.PtrTo(telem), false)
|
|
|
|
|
|
|
+ funcs["decLineVar"] = func(varname, decodedNilVarname string) string {
|
|
|
|
|
+ x.decVar(varname, decodedNilVarname, telem, false)
|
|
|
return ""
|
|
return ""
|
|
|
}
|
|
}
|
|
|
|
|
+ // funcs["decLineK"] = func(pfx string) string {
|
|
|
|
|
+ // x.decVar(ts.TempVar+pfx+ts.Rand, reflect.PtrTo(tkey), false)
|
|
|
|
|
+ // return ""
|
|
|
|
|
+ // }
|
|
|
|
|
+ // funcs["decLine"] = func(pfx string) string {
|
|
|
|
|
+ // x.decVar(ts.TempVar+pfx+ts.Rand, reflect.PtrTo(telem), false)
|
|
|
|
|
+ // return ""
|
|
|
|
|
+ // }
|
|
|
funcs["var"] = func(s string) string {
|
|
funcs["var"] = func(s string) string {
|
|
|
return ts.TempVar + s + ts.Rand
|
|
return ts.TempVar + s + ts.Rand
|
|
|
}
|
|
}
|
|
@@ -1430,18 +1447,19 @@ func (x *genRunner) decStructMapSwitch(kName string, varname string, rtid uintpt
|
|
|
for _, si := range tisfi {
|
|
for _, si := range tisfi {
|
|
|
x.line("case \"" + si.encName + "\":")
|
|
x.line("case \"" + si.encName + "\":")
|
|
|
var t2 reflect.StructField
|
|
var t2 reflect.StructField
|
|
|
- if si.i != -1 {
|
|
|
|
|
- t2 = t.Field(int(si.i))
|
|
|
|
|
- } else {
|
|
|
|
|
|
|
+ {
|
|
|
//we must accommodate anonymous fields, where the embedded field is a nil pointer in the value.
|
|
//we must accommodate anonymous fields, where the embedded field is a nil pointer in the value.
|
|
|
// t2 = t.FieldByIndex(si.is)
|
|
// t2 = t.FieldByIndex(si.is)
|
|
|
t2typ := t
|
|
t2typ := t
|
|
|
varname3 := varname
|
|
varname3 := varname
|
|
|
- for _, ix := range si.is {
|
|
|
|
|
|
|
+ for ij, ix := range si.is {
|
|
|
|
|
+ if uint8(ij) == si.nis {
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
for t2typ.Kind() == reflect.Ptr {
|
|
for t2typ.Kind() == reflect.Ptr {
|
|
|
t2typ = t2typ.Elem()
|
|
t2typ = t2typ.Elem()
|
|
|
}
|
|
}
|
|
|
- t2 = t2typ.Field(ix)
|
|
|
|
|
|
|
+ t2 = t2typ.Field(int(ix))
|
|
|
t2typ = t2.Type
|
|
t2typ = t2.Type
|
|
|
varname3 = varname3 + "." + t2.Name
|
|
varname3 = varname3 + "." + t2.Name
|
|
|
if t2typ.Kind() == reflect.Ptr {
|
|
if t2typ.Kind() == reflect.Ptr {
|
|
@@ -1449,7 +1467,7 @@ func (x *genRunner) decStructMapSwitch(kName string, varname string, rtid uintpt
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- x.decVar(varname+"."+t2.Name, t2.Type, false)
|
|
|
|
|
|
|
+ x.decVar(varname+"."+t2.Name, "", t2.Type, false)
|
|
|
}
|
|
}
|
|
|
x.line("default:")
|
|
x.line("default:")
|
|
|
// pass the slice here, so that the string will not escape, and maybe save allocation
|
|
// pass the slice here, so that the string will not escape, and maybe save allocation
|
|
@@ -1480,15 +1498,15 @@ func (x *genRunner) decStructMap(varname, lenvarname string, rtid uintptr, t ref
|
|
|
x.linef("if %shl%s { if %sj%s >= %s { break }", tpfx, i, tpfx, i, lenvarname)
|
|
x.linef("if %shl%s { if %sj%s >= %s { break }", tpfx, i, tpfx, i, lenvarname)
|
|
|
x.line("} else { if r.CheckBreak() { break }; }")
|
|
x.line("} else { if r.CheckBreak() { break }; }")
|
|
|
}
|
|
}
|
|
|
- x.linef("z.DecSendContainerState(codecSelfer_containerMapKey%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.ReadMapElemKey()") // f("z.DecSendContainerState(codecSelfer_containerMapKey%s)", x.xs)
|
|
|
x.line(kName + "Slc = r.DecodeStringAsBytes()")
|
|
x.line(kName + "Slc = r.DecodeStringAsBytes()")
|
|
|
// let string be scoped to this loop alone, so it doesn't escape.
|
|
// let string be scoped to this loop alone, so it doesn't escape.
|
|
|
x.line(kName + " := string(" + kName + "Slc)")
|
|
x.line(kName + " := string(" + kName + "Slc)")
|
|
|
- x.linef("z.DecSendContainerState(codecSelfer_containerMapValue%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.ReadMapElemValue()") // f("z.DecSendContainerState(codecSelfer_containerMapValue%s)", x.xs)
|
|
|
x.decStructMapSwitch(kName, varname, rtid, t)
|
|
x.decStructMapSwitch(kName, varname, rtid, t)
|
|
|
|
|
|
|
|
x.line("} // end for " + tpfx + "j" + i)
|
|
x.line("} // end for " + tpfx + "j" + i)
|
|
|
- x.linef("z.DecSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.ReadMapEnd()") // f("z.DecSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (x *genRunner) decStructArray(varname, lenvarname, breakString string, rtid uintptr, t reflect.Type) {
|
|
func (x *genRunner) decStructArray(varname, lenvarname, breakString string, rtid uintptr, t reflect.Type) {
|
|
@@ -1501,18 +1519,19 @@ func (x *genRunner) decStructArray(varname, lenvarname, breakString string, rtid
|
|
|
x.linef("var %shl%s bool = %s >= 0", tpfx, i, lenvarname) // has length
|
|
x.linef("var %shl%s bool = %s >= 0", tpfx, i, lenvarname) // has length
|
|
|
for _, si := range tisfi {
|
|
for _, si := range tisfi {
|
|
|
var t2 reflect.StructField
|
|
var t2 reflect.StructField
|
|
|
- if si.i != -1 {
|
|
|
|
|
- t2 = t.Field(int(si.i))
|
|
|
|
|
- } else {
|
|
|
|
|
|
|
+ {
|
|
|
//we must accommodate anonymous fields, where the embedded field is a nil pointer in the value.
|
|
//we must accommodate anonymous fields, where the embedded field is a nil pointer in the value.
|
|
|
// t2 = t.FieldByIndex(si.is)
|
|
// t2 = t.FieldByIndex(si.is)
|
|
|
t2typ := t
|
|
t2typ := t
|
|
|
varname3 := varname
|
|
varname3 := varname
|
|
|
- for _, ix := range si.is {
|
|
|
|
|
|
|
+ for ij, ix := range si.is {
|
|
|
|
|
+ if uint8(ij) == si.nis {
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
for t2typ.Kind() == reflect.Ptr {
|
|
for t2typ.Kind() == reflect.Ptr {
|
|
|
t2typ = t2typ.Elem()
|
|
t2typ = t2typ.Elem()
|
|
|
}
|
|
}
|
|
|
- t2 = t2typ.Field(ix)
|
|
|
|
|
|
|
+ t2 = t2typ.Field(int(ix))
|
|
|
t2typ = t2.Type
|
|
t2typ = t2.Type
|
|
|
varname3 = varname3 + "." + t2.Name
|
|
varname3 = varname3 + "." + t2.Name
|
|
|
if t2typ.Kind() == reflect.Ptr {
|
|
if t2typ.Kind() == reflect.Ptr {
|
|
@@ -1524,10 +1543,10 @@ func (x *genRunner) decStructArray(varname, lenvarname, breakString string, rtid
|
|
|
x.linef("%sj%s++; if %shl%s { %sb%s = %sj%s > %s } else { %sb%s = r.CheckBreak() }",
|
|
x.linef("%sj%s++; if %shl%s { %sb%s = %sj%s > %s } else { %sb%s = r.CheckBreak() }",
|
|
|
tpfx, i, tpfx, i, tpfx, i,
|
|
tpfx, i, tpfx, i, tpfx, i,
|
|
|
tpfx, i, lenvarname, tpfx, i)
|
|
tpfx, i, lenvarname, tpfx, i)
|
|
|
- x.linef("if %sb%s { z.DecSendContainerState(codecSelfer_containerArrayEnd%s); %s }",
|
|
|
|
|
- tpfx, i, x.xs, breakString)
|
|
|
|
|
- x.linef("z.DecSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
|
|
|
|
|
- x.decVar(varname+"."+t2.Name, t2.Type, true)
|
|
|
|
|
|
|
+ x.linef("if %sb%s { r.ReadArrayEnd(); %s }", tpfx, i, breakString)
|
|
|
|
|
+ // x.linef("if %sb%s { z.DecSendContainerState(codecSelfer_containerArrayEnd%s); %s }", tpfx, i, x.xs, breakString)
|
|
|
|
|
+ x.line("r.ReadArrayElem()") // f("z.DecSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
|
|
|
|
|
+ x.decVar(varname+"."+t2.Name, "", t2.Type, true)
|
|
|
}
|
|
}
|
|
|
// read remaining values and throw away.
|
|
// read remaining values and throw away.
|
|
|
x.line("for {")
|
|
x.line("for {")
|
|
@@ -1535,10 +1554,10 @@ func (x *genRunner) decStructArray(varname, lenvarname, breakString string, rtid
|
|
|
tpfx, i, tpfx, i, tpfx, i,
|
|
tpfx, i, tpfx, i, tpfx, i,
|
|
|
tpfx, i, lenvarname, tpfx, i)
|
|
tpfx, i, lenvarname, tpfx, i)
|
|
|
x.linef("if %sb%s { break }", tpfx, i)
|
|
x.linef("if %sb%s { break }", tpfx, i)
|
|
|
- x.linef("z.DecSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.ReadArrayElem()") // f("z.DecSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
|
|
|
x.linef(`z.DecStructFieldNotFound(%sj%s - 1, "")`, tpfx, i)
|
|
x.linef(`z.DecStructFieldNotFound(%sj%s - 1, "")`, tpfx, i)
|
|
|
x.line("}")
|
|
x.line("}")
|
|
|
- x.linef("z.DecSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.ReadArrayEnd()") // f("z.DecSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (x *genRunner) decStruct(varname string, rtid uintptr, t reflect.Type) {
|
|
func (x *genRunner) decStruct(varname string, rtid uintptr, t reflect.Type) {
|
|
@@ -1548,7 +1567,7 @@ func (x *genRunner) decStruct(varname string, rtid uintptr, t reflect.Type) {
|
|
|
x.linef("if %sct%s == codecSelferValueTypeMap%s {", genTempVarPfx, i, x.xs)
|
|
x.linef("if %sct%s == codecSelferValueTypeMap%s {", genTempVarPfx, i, x.xs)
|
|
|
x.line(genTempVarPfx + "l" + i + " := r.ReadMapStart()")
|
|
x.line(genTempVarPfx + "l" + i + " := r.ReadMapStart()")
|
|
|
x.linef("if %sl%s == 0 {", genTempVarPfx, i)
|
|
x.linef("if %sl%s == 0 {", genTempVarPfx, i)
|
|
|
- x.linef("z.DecSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.ReadMapEnd()") // f("z.DecSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
|
|
|
if genUseOneFunctionForDecStructMap {
|
|
if genUseOneFunctionForDecStructMap {
|
|
|
x.line("} else { ")
|
|
x.line("} else { ")
|
|
|
x.linef("x.codecDecodeSelfFromMap(%sl%s, d)", genTempVarPfx, i)
|
|
x.linef("x.codecDecodeSelfFromMap(%sl%s, d)", genTempVarPfx, i)
|
|
@@ -1564,7 +1583,7 @@ func (x *genRunner) decStruct(varname string, rtid uintptr, t reflect.Type) {
|
|
|
x.linef("} else if %sct%s == codecSelferValueTypeArray%s {", genTempVarPfx, i, x.xs)
|
|
x.linef("} else if %sct%s == codecSelferValueTypeArray%s {", genTempVarPfx, i, x.xs)
|
|
|
x.line(genTempVarPfx + "l" + i + " := r.ReadArrayStart()")
|
|
x.line(genTempVarPfx + "l" + i + " := r.ReadArrayStart()")
|
|
|
x.linef("if %sl%s == 0 {", genTempVarPfx, i)
|
|
x.linef("if %sl%s == 0 {", genTempVarPfx, i)
|
|
|
- x.linef("z.DecSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
|
|
|
|
|
|
|
+ x.line("r.ReadArrayEnd()") // f("z.DecSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
|
|
|
x.line("} else { ")
|
|
x.line("} else { ")
|
|
|
x.linef("x.codecDecodeSelfFromArray(%sl%s, d)", genTempVarPfx, i)
|
|
x.linef("x.codecDecodeSelfFromArray(%sl%s, d)", genTempVarPfx, i)
|
|
|
x.line("}")
|
|
x.line("}")
|