1
2
3
4
5
6
7 package codec
8
9 import (
10 "bytes"
11 "encoding/base32"
12 "errors"
13 "fmt"
14 "go/format"
15 "io"
16 "io/ioutil"
17 "math/rand"
18 "os"
19 "reflect"
20 "regexp"
21 "sort"
22 "strconv"
23 "strings"
24 "sync"
25 "text/template"
26 "time"
27
28 "unicode"
29 "unicode/utf8"
30 )
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156 const genVersion = 28
157
158 const (
159 genCodecPkg = "codec1978"
160 genTempVarPfx = "yy"
161 genTopLevelVarName = "x"
162
163
164
165 genAnythingCanBeNil = true
166
167
168
169 genStructCanonical = true
170
171
172
173
174
175 genFastpathCanonical = true
176
177
178 genFastpathTrimTypes = true
179 )
180
181 type genStringDecAsBytes string
182 type genStringDecZC string
183
184 var genStringDecAsBytesTyp = reflect.TypeOf(genStringDecAsBytes(""))
185 var genStringDecZCTyp = reflect.TypeOf(genStringDecZC(""))
186 var genFormats = []string{"Json", "Cbor", "Msgpack", "Binc", "Simple"}
187
188 var (
189 errGenAllTypesSamePkg = errors.New("All types must be in the same package")
190 errGenExpectArrayOrMap = errors.New("unexpected type - expecting array/map/slice")
191 errGenUnexpectedTypeFastpath = errors.New("fast-path: unexpected type - requires map or slice")
192
193
194
195
196
197 genTypenameEnc = base32.NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef")
198 genQNameRegex = regexp.MustCompile(`[A-Za-z_.]+`)
199 )
200
201 type genBuf struct {
202 buf []byte
203 }
204
205 func (x *genBuf) sIf(b bool, s, t string) *genBuf {
206 if b {
207 x.buf = append(x.buf, s...)
208 } else {
209 x.buf = append(x.buf, t...)
210 }
211 return x
212 }
213 func (x *genBuf) s(s string) *genBuf { x.buf = append(x.buf, s...); return x }
214 func (x *genBuf) b(s []byte) *genBuf { x.buf = append(x.buf, s...); return x }
215 func (x *genBuf) v() string { return string(x.buf) }
216 func (x *genBuf) f(s string, args ...interface{}) { x.s(fmt.Sprintf(s, args...)) }
217 func (x *genBuf) reset() {
218 if x.buf != nil {
219 x.buf = x.buf[:0]
220 }
221 }
222
223
224 type genRunner struct {
225 w io.Writer
226 c uint64
227 f uint64
228
229 t []reflect.Type
230 tc reflect.Type
231 te map[uintptr]bool
232 td map[uintptr]bool
233 tz map[uintptr]bool
234
235 cp string
236
237 im map[string]reflect.Type
238 imn map[string]string
239 imc uint64
240
241 is map[reflect.Type]struct{}
242 bp string
243
244 cpfx string
245
246 ty map[reflect.Type]struct{}
247 tm map[reflect.Type]struct{}
248 ts []reflect.Type
249
250 xs string
251 hn string
252
253 ti *TypeInfos
254
255
256 jsonOnlyWhen, toArrayWhen, omitEmptyWhen *bool
257
258 nx bool
259 }
260
261 type genIfClause struct {
262 hasIf bool
263 }
264
265 func (g *genIfClause) end(x *genRunner) {
266 if g.hasIf {
267 x.line("}")
268 }
269 }
270
271 func (g *genIfClause) c(last bool) (v string) {
272 if last {
273 if g.hasIf {
274 v = " } else { "
275 }
276 } else if g.hasIf {
277 v = " } else if "
278 } else {
279 v = "if "
280 g.hasIf = true
281 }
282 return
283 }
284
285
286
287
288
289 func Gen(w io.Writer, buildTags, pkgName, uid string, noExtensions bool,
290 jsonOnlyWhen, toArrayWhen, omitEmptyWhen *bool,
291 ti *TypeInfos, types ...reflect.Type) (warnings []string) {
292
293
294
295
296 if len(types) == 0 {
297 return
298 }
299 x := genRunner{
300 w: w,
301 t: types,
302 te: make(map[uintptr]bool),
303 td: make(map[uintptr]bool),
304 tz: make(map[uintptr]bool),
305 im: make(map[string]reflect.Type),
306 imn: make(map[string]string),
307 is: make(map[reflect.Type]struct{}),
308 tm: make(map[reflect.Type]struct{}),
309 ty: make(map[reflect.Type]struct{}),
310 ts: []reflect.Type{},
311 bp: genImportPath(types[0]),
312 xs: uid,
313 ti: ti,
314 jsonOnlyWhen: jsonOnlyWhen,
315 toArrayWhen: toArrayWhen,
316 omitEmptyWhen: omitEmptyWhen,
317
318 nx: noExtensions,
319 }
320 if x.ti == nil {
321 x.ti = defTypeInfos
322 }
323 if x.xs == "" {
324 rr := rand.New(rand.NewSource(time.Now().UnixNano()))
325 x.xs = strconv.FormatInt(rr.Int63n(9999), 10)
326 }
327
328
329 x.cp = genImportPath(reflect.TypeOf(x))
330 x.imn[x.cp] = genCodecPkg
331
332
333 for i := 0; i < len(x.t); {
334 t := x.t[i]
335
336 if genImportPath(t) != x.bp {
337 halt.onerror(errGenAllTypesSamePkg)
338 }
339 ti1 := x.ti.get(rt2id(t), t)
340 if ti1.flagMissingFielder || ti1.flagMissingFielderPtr {
341
342 warnings = append(warnings, fmt.Sprintf("type: '%v' not generated; implements codec.MissingFielder", t))
343 copy(x.t[i:], x.t[i+1:])
344 x.t = x.t[:len(x.t)-1]
345 continue
346 }
347 x.genRefPkgs(t)
348 i++
349 }
350
351 x.line("// +build go1.6")
352 if buildTags != "" {
353 x.line("// +build " + buildTags)
354 }
355 x.line(`
356
357 // Code generated by codecgen - DO NOT EDIT.
358
359 `)
360 x.line("package " + pkgName)
361 x.line("")
362 x.line("import (")
363 if x.cp != x.bp {
364 x.cpfx = genCodecPkg + "."
365 x.linef("%s \"%s\"", genCodecPkg, x.cp)
366 }
367
368 imKeys := make([]string, 0, len(x.im))
369 for k := range x.im {
370 imKeys = append(imKeys, k)
371 }
372 sort.Strings(imKeys)
373 for _, k := range imKeys {
374 if k == x.imn[k] {
375 x.linef("\"%s\"", k)
376 } else {
377 x.linef("%s \"%s\"", x.imn[k], k)
378 }
379 }
380
381 for _, k := range [...]string{"runtime", "errors", "strconv", "sort"} {
382 if _, ok := x.im[k]; !ok {
383 x.line("\"" + k + "\"")
384 }
385 }
386 x.line(")")
387 x.line("")
388
389 x.line("const (")
390 x.linef("// ----- content types ----")
391 x.linef("codecSelferCcUTF8%s = %v", x.xs, int64(cUTF8))
392 x.linef("codecSelferCcRAW%s = %v", x.xs, int64(cRAW))
393 x.linef("// ----- value types used ----")
394 for _, vt := range [...]valueType{
395 valueTypeArray, valueTypeMap, valueTypeString,
396 valueTypeInt, valueTypeUint, valueTypeFloat,
397 valueTypeNil,
398 } {
399 x.linef("codecSelferValueType%s%s = %v", vt.String(), x.xs, int64(vt))
400 }
401
402 x.linef("codecSelferBitsize%s = uint8(32 << (^uint(0) >> 63))", x.xs)
403 x.linef("codecSelferDecContainerLenNil%s = %d", x.xs, int64(containerLenNil))
404 x.line(")")
405 x.line("var (")
406 x.line("errCodecSelferOnlyMapOrArrayEncodeToStruct" + x.xs + " = " + "errors.New(`only encoded map or array can be decoded into a struct`)")
407 x.line("_ sort.Interface = nil")
408 x.line(")")
409 x.line("")
410
411 x.hn = "codecSelfer" + x.xs
412 x.line("type " + x.hn + " struct{}")
413 x.line("")
414 x.linef("func %sFalse() bool { return false }", x.hn)
415 x.linef("func %sTrue() bool { return true }", x.hn)
416 x.line("")
417
418
419 for _, s := range []string{"string", "uint64", "int64", "float64"} {
420 x.linef("type %s%sSlice []%s", x.hn, s, s)
421 x.linef("func (p %s%sSlice) Len() int { return len(p) }", x.hn, s)
422 x.linef("func (p %s%sSlice) Swap(i, j int) { p[uint(i)], p[uint(j)] = p[uint(j)], p[uint(i)] }", x.hn, s)
423 x.linef("func (p %s%sSlice) Less(i, j int) bool { return p[uint(i)] < p[uint(j)] }", x.hn, s)
424 }
425
426 x.line("")
427 x.varsfxreset()
428 x.line("func init() {")
429 x.linef("if %sGenVersion != %v {", x.cpfx, genVersion)
430 x.line("_, file, _, _ := runtime.Caller(0)")
431 x.linef("ver := strconv.FormatInt(int64(%sGenVersion), 10)", x.cpfx)
432 x.outf(`panic(errors.New("codecgen version mismatch: current: %v, need " + ver + ". Re-generate file: " + file))`, genVersion)
433 x.linef("}")
434 if len(imKeys) > 0 {
435 x.line("if false { // reference the types, but skip this branch at build/run time")
436 for _, k := range imKeys {
437 t := x.im[k]
438 x.linef("var _ %s.%s", x.imn[k], t.Name())
439 }
440 x.line("} ")
441 }
442 x.line("}")
443 x.line("")
444
445
446 for _, t := range x.t {
447 x.tc = t
448 x.linef("func (%s) codecSelferViaCodecgen() {}", x.genTypeName(t))
449 x.selfer(true)
450 x.selfer(false)
451 x.tryGenIsZero(t)
452 }
453
454 for _, t := range x.ts {
455 rtid := rt2id(t)
456
457 x.varsfxreset()
458 x.linef("func (x %s) enc%s(v %s%s, e *%sEncoder) {", x.hn, x.genMethodNameT(t), x.arr2str(t, "*"), x.genTypeName(t), x.cpfx)
459 x.genRequiredMethodVars(true)
460 switch t.Kind() {
461 case reflect.Array, reflect.Slice, reflect.Chan:
462 x.encListFallback("v", t)
463 case reflect.Map:
464 x.encMapFallback("v", t)
465 default:
466 halt.onerror(errGenExpectArrayOrMap)
467 }
468 x.line("}")
469 x.line("")
470
471
472 x.varsfxreset()
473 x.linef("func (x %s) dec%s(v *%s, d *%sDecoder) {", x.hn, x.genMethodNameT(t), x.genTypeName(t), x.cpfx)
474 x.genRequiredMethodVars(false)
475 switch t.Kind() {
476 case reflect.Array, reflect.Slice, reflect.Chan:
477 x.decListFallback("v", rtid, t)
478 case reflect.Map:
479 x.decMapFallback("v", rtid, t)
480 default:
481 halt.onerror(errGenExpectArrayOrMap)
482 }
483 x.line("}")
484 x.line("")
485 }
486
487 for t := range x.ty {
488 x.tryGenIsZero(t)
489 x.line("")
490 }
491
492 x.line("")
493 return
494 }
495
496 func (x *genRunner) checkForSelfer(t reflect.Type, varname string) bool {
497
498
499 return varname != genTopLevelVarName
500 }
501
502 func (x *genRunner) arr2str(t reflect.Type, s string) string {
503 if t.Kind() == reflect.Array {
504 return s
505 }
506 return ""
507 }
508
509 func (x *genRunner) genRequiredMethodVars(encode bool) {
510 x.line("var h " + x.hn)
511 if encode {
512 x.line("z, r := " + x.cpfx + "GenHelper().Encoder(e)")
513 } else {
514 x.line("z, r := " + x.cpfx + "GenHelper().Decoder(d)")
515 }
516 x.line("_, _, _ = h, z, r")
517 }
518
519 func (x *genRunner) genRefPkgs(t reflect.Type) {
520 if _, ok := x.is[t]; ok {
521 return
522 }
523 x.is[t] = struct{}{}
524 tpkg, tname := genImportPath(t), t.Name()
525 if tpkg != "" && tpkg != x.bp && tpkg != x.cp && tname != "" && tname[0] >= 'A' && tname[0] <= 'Z' {
526 if _, ok := x.im[tpkg]; !ok {
527 x.im[tpkg] = t
528 if idx := strings.LastIndex(tpkg, "/"); idx < 0 {
529 x.imn[tpkg] = tpkg
530 } else {
531 x.imc++
532 x.imn[tpkg] = "pkg" + strconv.FormatUint(x.imc, 10) + "_" + genGoIdentifier(tpkg[idx+1:], false)
533 }
534 }
535 }
536 switch t.Kind() {
537 case reflect.Array, reflect.Slice, reflect.Ptr, reflect.Chan:
538 x.genRefPkgs(t.Elem())
539 case reflect.Map:
540 x.genRefPkgs(t.Elem())
541 x.genRefPkgs(t.Key())
542 case reflect.Struct:
543 for i := 0; i < t.NumField(); i++ {
544 if fname := t.Field(i).Name; fname != "" && fname[0] >= 'A' && fname[0] <= 'Z' {
545 x.genRefPkgs(t.Field(i).Type)
546 }
547 }
548 }
549 }
550
551
552 func (x *genRunner) sayFalse() string {
553 x.f++
554 if x.f%2 == 0 {
555 return x.hn + "False()"
556 }
557 return "false"
558 }
559
560
561 func (x *genRunner) sayTrue() string {
562 x.f++
563 if x.f%2 == 0 {
564 return x.hn + "True()"
565 }
566 return "true"
567 }
568
569 func (x *genRunner) varsfx() string {
570 x.c++
571 return strconv.FormatUint(x.c, 10)
572 }
573
574 func (x *genRunner) varsfxreset() {
575 x.c = 0
576 }
577
578 func (x *genRunner) out(s string) {
579 _, err := io.WriteString(x.w, s)
580 genCheckErr(err)
581 }
582
583 func (x *genRunner) outf(s string, params ...interface{}) {
584 _, err := fmt.Fprintf(x.w, s, params...)
585 genCheckErr(err)
586 }
587
588 func (x *genRunner) line(s string) {
589 x.out(s)
590 if len(s) == 0 || s[len(s)-1] != '\n' {
591 x.out("\n")
592 }
593 }
594
595 func (x *genRunner) lineIf(s string) {
596 if s != "" {
597 x.line(s)
598 }
599 }
600
601 func (x *genRunner) linef(s string, params ...interface{}) {
602 x.outf(s, params...)
603 if len(s) == 0 || s[len(s)-1] != '\n' {
604 x.out("\n")
605 }
606 }
607
608 func (x *genRunner) genTypeName(t reflect.Type) (n string) {
609
610
611
612
613
614 var ptrPfx string
615 for t.Kind() == reflect.Ptr {
616 ptrPfx += "*"
617 t = t.Elem()
618 }
619 if tn := t.Name(); tn != "" {
620 return ptrPfx + x.genTypeNamePrim(t)
621 }
622 switch t.Kind() {
623 case reflect.Map:
624 return ptrPfx + "map[" + x.genTypeName(t.Key()) + "]" + x.genTypeName(t.Elem())
625 case reflect.Slice:
626 return ptrPfx + "[]" + x.genTypeName(t.Elem())
627 case reflect.Array:
628 return ptrPfx + "[" + strconv.FormatInt(int64(t.Len()), 10) + "]" + x.genTypeName(t.Elem())
629 case reflect.Chan:
630 return ptrPfx + t.ChanDir().String() + " " + x.genTypeName(t.Elem())
631 default:
632 if t == intfTyp {
633 return ptrPfx + "interface{}"
634 } else {
635 return ptrPfx + x.genTypeNamePrim(t)
636 }
637 }
638 }
639
640 func (x *genRunner) genTypeNamePrim(t reflect.Type) (n string) {
641 if t.Name() == "" {
642 return t.String()
643 } else if genImportPath(t) == "" || genImportPath(t) == genImportPath(x.tc) {
644 return t.Name()
645 } else {
646 return x.imn[genImportPath(t)] + "." + t.Name()
647
648 }
649 }
650
651 func (x *genRunner) genZeroValueR(t reflect.Type) string {
652
653 switch t.Kind() {
654 case reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func,
655 reflect.Slice, reflect.Map, reflect.Invalid:
656 return "nil"
657 case reflect.Bool:
658 return "false"
659 case reflect.String:
660 return `""`
661 case reflect.Struct, reflect.Array:
662 return x.genTypeName(t) + "{}"
663 default:
664 return "0"
665 }
666 }
667
668 func (x *genRunner) genMethodNameT(t reflect.Type) (s string) {
669 return genMethodNameT(t, x.tc)
670 }
671
672 func (x *genRunner) tryGenIsZero(t reflect.Type) (done bool) {
673 if t.Kind() != reflect.Struct || t.Implements(isCodecEmptyerTyp) {
674 return
675 }
676
677 rtid := rt2id(t)
678
679 if _, ok := x.tz[rtid]; ok {
680 delete(x.ty, t)
681 return
682 }
683
684 x.tz[rtid] = true
685 delete(x.ty, t)
686
687 ti := x.ti.get(rtid, t)
688 tisfi := ti.sfi.source()
689 varname := genTopLevelVarName
690
691 x.linef("func (%s *%s) IsCodecEmpty() bool {", varname, x.genTypeName(t))
692
693 anonSeen := make(map[reflect.Type]bool)
694 var omitline genBuf
695 for _, si := range tisfi {
696 if si.path.parent != nil {
697 root := si.path.root()
698 if anonSeen[root.typ] {
699 continue
700 }
701 anonSeen[root.typ] = true
702 }
703 t2 := genOmitEmptyLinePreChecks(varname, t, si, &omitline, true)
704
705 if t2.Type.Kind() != reflect.Ptr {
706 x.doEncOmitEmptyLine(t2, varname, &omitline)
707 omitline.s(" || ")
708 }
709 }
710 omitline.s(" false")
711 x.linef("return !(%s)", omitline.v())
712
713 x.line("}")
714 x.line("")
715 return true
716 }
717
718 func (x *genRunner) selfer(encode bool) {
719 t := x.tc
720
721 t0 := t
722
723
724 isptr := !encode || t.Kind() == reflect.Array || (t.Kind() == reflect.Struct && t != timeTyp)
725 x.varsfxreset()
726
727 fnSigPfx := "func (" + genTopLevelVarName + " "
728 if isptr {
729 fnSigPfx += "*"
730 }
731 fnSigPfx += x.genTypeName(t)
732 x.out(fnSigPfx)
733
734 if isptr {
735 t = reflect.PtrTo(t)
736 }
737 if encode {
738 x.line(") CodecEncodeSelf(e *" + x.cpfx + "Encoder) {")
739 x.genRequiredMethodVars(true)
740 if t0.Kind() == reflect.Struct {
741 x.linef("if z.EncBasicHandle().CheckCircularRef { z.EncEncode(%s); return }", genTopLevelVarName)
742 }
743 x.encVar(genTopLevelVarName, t)
744 } else {
745 x.line(") CodecDecodeSelf(d *" + x.cpfx + "Decoder) {")
746 x.genRequiredMethodVars(false)
747
748
749
750
751 x.dec(genTopLevelVarName, t0, true)
752 }
753 x.line("}")
754 x.line("")
755
756 if encode || t0.Kind() != reflect.Struct {
757 return
758 }
759
760
761 x.out(fnSigPfx)
762 x.line(") codecDecodeSelfFromMap(l int, d *" + x.cpfx + "Decoder) {")
763 x.genRequiredMethodVars(false)
764 x.decStructMap(genTopLevelVarName, "l", rt2id(t0), t0)
765 x.line("}")
766 x.line("")
767
768
769 x.out(fnSigPfx)
770 x.line(") codecDecodeSelfFromArray(l int, d *" + x.cpfx + "Decoder) {")
771 x.genRequiredMethodVars(false)
772 x.decStructArray(genTopLevelVarName, "l", "return", rt2id(t0), t0)
773 x.line("}")
774 x.line("")
775
776 }
777
778
779 func (x *genRunner) xtraSM(varname string, t reflect.Type, ti *typeInfo, encode, isptr bool) {
780 var ptrPfx, addrPfx string
781 if isptr {
782 ptrPfx = "*"
783 } else {
784 addrPfx = "&"
785 }
786 if encode {
787 x.linef("h.enc%s((%s%s)(%s), e)", x.genMethodNameT(t), ptrPfx, x.genTypeName(t), varname)
788 } else {
789 x.linef("h.dec%s((*%s)(%s%s), d)", x.genMethodNameT(t), x.genTypeName(t), addrPfx, varname)
790 }
791 x.registerXtraT(t, ti)
792 }
793
794 func (x *genRunner) registerXtraT(t reflect.Type, ti *typeInfo) {
795
796 tk := t.Kind()
797 if tk == reflect.Ptr {
798 x.registerXtraT(t.Elem(), nil)
799 return
800 }
801 if _, ok := x.tm[t]; ok {
802 return
803 }
804
805 switch tk {
806 case reflect.Chan, reflect.Slice, reflect.Array, reflect.Map:
807 default:
808 return
809 }
810
811 if ti == nil {
812 ti = x.ti.get(rt2id(t), t)
813 }
814 if _, rtidu := genFastpathUnderlying(t, ti.rtid, ti); fastpathAvIndex(rtidu) != -1 {
815 return
816 }
817 x.tm[t] = struct{}{}
818 x.ts = append(x.ts, t)
819
820 x.registerXtraT(t.Elem(), nil)
821 if tk == reflect.Map {
822 x.registerXtraT(t.Key(), nil)
823 }
824 }
825
826
827
828 func (x *genRunner) encVar(varname string, t reflect.Type) {
829 var checkNil bool
830
831
832 switch t.Kind() {
833 case reflect.Ptr, reflect.Interface, reflect.Chan:
834 checkNil = true
835 }
836 x.encVarChkNil(varname, t, checkNil)
837 }
838
839 func (x *genRunner) encVarChkNil(varname string, t reflect.Type, checkNil bool) {
840 if checkNil {
841 x.linef("if %s == nil { r.EncodeNil() } else {", varname)
842 }
843
844 switch t.Kind() {
845 case reflect.Ptr:
846 telem := t.Elem()
847 tek := telem.Kind()
848 if tek == reflect.Array || (tek == reflect.Struct && telem != timeTyp) {
849 x.enc(varname, genNonPtr(t), true)
850 break
851 }
852 i := x.varsfx()
853 x.line(genTempVarPfx + i + " := *" + varname)
854 x.enc(genTempVarPfx+i, genNonPtr(t), false)
855 case reflect.Struct, reflect.Array:
856 if t == timeTyp {
857 x.enc(varname, t, false)
858 break
859 }
860 i := x.varsfx()
861 x.line(genTempVarPfx + i + " := &" + varname)
862 x.enc(genTempVarPfx+i, t, true)
863 default:
864 x.enc(varname, t, false)
865 }
866
867 if checkNil {
868 x.line("}")
869 }
870 }
871
872
873
874
875
876 func (x *genRunner) enc(varname string, t reflect.Type, isptr bool) {
877 rtid := rt2id(t)
878 ti2 := x.ti.get(rtid, t)
879
880
881
882
883
884 mi := x.varsfx()
885
886
887
888
889
890
891
892 var hasIf genIfClause
893 defer hasIf.end(x)
894
895 var ptrPfx, addrPfx string
896 if isptr {
897 ptrPfx = "*"
898 } else {
899 addrPfx = "&"
900 }
901
902 if t == timeTyp {
903 x.linef("%s z.EncBasicHandle().TimeBuiltin() { r.EncodeTime(%s%s)", hasIf.c(false), ptrPfx, varname)
904
905 }
906 if t == rawTyp {
907 x.linef("%s z.EncRaw(%s%s)", hasIf.c(true), ptrPfx, varname)
908 return
909 }
910 if t == rawExtTyp {
911 x.linef("%s r.EncodeRawExt(%s%s)", hasIf.c(true), addrPfx, varname)
912 return
913 }
914
915
916
917 if !x.nx && varname != genTopLevelVarName && t != genStringDecAsBytesTyp &&
918 t != genStringDecZCTyp && genImportPath(t) != "" && t.Name() != "" {
919 yy := fmt.Sprintf("%sxt%s", genTempVarPfx, mi)
920 x.linef("%s %s := z.Extension(%s); %s != nil { z.EncExtension(%s, %s) ",
921 hasIf.c(false), yy, varname, yy, varname, yy)
922 }
923
924 if x.checkForSelfer(t, varname) {
925 if ti2.flagSelfer {
926 x.linef("%s %s.CodecEncodeSelf(e)", hasIf.c(true), varname)
927 return
928 }
929 if ti2.flagSelferPtr {
930 if isptr {
931 x.linef("%s %s.CodecEncodeSelf(e)", hasIf.c(true), varname)
932 } else {
933 x.linef("%s %ssf%s := &%s", hasIf.c(true), genTempVarPfx, mi, varname)
934 x.linef("%ssf%s.CodecEncodeSelf(e)", genTempVarPfx, mi)
935 }
936 return
937 }
938
939 if _, ok := x.te[rtid]; ok {
940 x.linef("%s %s.CodecEncodeSelf(e)", hasIf.c(true), varname)
941 return
942 }
943 }
944
945 inlist := false
946 for _, t0 := range x.t {
947 if t == t0 {
948 inlist = true
949 if x.checkForSelfer(t, varname) {
950 x.linef("%s %s.CodecEncodeSelf(e)", hasIf.c(true), varname)
951 return
952 }
953 break
954 }
955 }
956
957 var rtidAdded bool
958 if t == x.tc {
959 x.te[rtid] = true
960 rtidAdded = true
961 }
962
963 if ti2.flagBinaryMarshaler {
964 x.linef("%s z.EncBinary() { z.EncBinaryMarshal(%s%v) ", hasIf.c(false), ptrPfx, varname)
965 } else if ti2.flagBinaryMarshalerPtr {
966 x.linef("%s z.EncBinary() { z.EncBinaryMarshal(%s%v) ", hasIf.c(false), addrPfx, varname)
967 }
968
969 if ti2.flagJsonMarshaler {
970 x.linef("%s !z.EncBinary() && z.IsJSONHandle() { z.EncJSONMarshal(%s%v) ", hasIf.c(false), ptrPfx, varname)
971 } else if ti2.flagJsonMarshalerPtr {
972 x.linef("%s !z.EncBinary() && z.IsJSONHandle() { z.EncJSONMarshal(%s%v) ", hasIf.c(false), addrPfx, varname)
973 } else if ti2.flagTextMarshaler {
974 x.linef("%s !z.EncBinary() { z.EncTextMarshal(%s%v) ", hasIf.c(false), ptrPfx, varname)
975 } else if ti2.flagTextMarshalerPtr {
976 x.linef("%s !z.EncBinary() { z.EncTextMarshal(%s%v) ", hasIf.c(false), addrPfx, varname)
977 }
978
979 x.lineIf(hasIf.c(true))
980
981 switch t.Kind() {
982 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
983 x.line("r.EncodeInt(int64(" + varname + "))")
984 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
985 x.line("r.EncodeUint(uint64(" + varname + "))")
986 case reflect.Float32:
987 x.line("r.EncodeFloat32(float32(" + varname + "))")
988 case reflect.Float64:
989 x.line("r.EncodeFloat64(float64(" + varname + "))")
990 case reflect.Complex64:
991 x.linef("z.EncEncodeComplex64(complex64(%s))", varname)
992 case reflect.Complex128:
993 x.linef("z.EncEncodeComplex128(complex128(%s))", varname)
994 case reflect.Bool:
995 x.line("r.EncodeBool(bool(" + varname + "))")
996 case reflect.String:
997 x.linef("r.EncodeString(string(%s))", varname)
998 case reflect.Chan:
999 x.xtraSM(varname, t, ti2, true, false)
1000
1001 case reflect.Array:
1002 _, rtidu := genFastpathUnderlying(t, rtid, ti2)
1003 if fastpathAvIndex(rtidu) != -1 {
1004 g := x.newFastpathGenV(ti2.key)
1005 x.linef("z.F.%sV((%s)(%s[:]), e)", g.MethodNamePfx("Enc", false), x.genTypeName(ti2.key), varname)
1006 } else {
1007 x.xtraSM(varname, t, ti2, true, true)
1008 }
1009 case reflect.Slice:
1010
1011
1012
1013
1014
1015
1016
1017 x.linef("if %s == nil { r.EncodeNil() } else {", varname)
1018 if rtid == uint8SliceTypId {
1019 x.line("r.EncodeStringBytesRaw([]byte(" + varname + "))")
1020 } else {
1021 tu, rtidu := genFastpathUnderlying(t, rtid, ti2)
1022 if fastpathAvIndex(rtidu) != -1 {
1023 g := x.newFastpathGenV(tu)
1024 if rtid == rtidu {
1025 x.linef("z.F.%sV(%s, e)", g.MethodNamePfx("Enc", false), varname)
1026 } else {
1027 x.linef("z.F.%sV((%s)(%s), e)", g.MethodNamePfx("Enc", false), x.genTypeName(tu), varname)
1028 }
1029 } else {
1030 x.xtraSM(varname, t, ti2, true, false)
1031 }
1032 }
1033 x.linef("} // end block: if %s slice == nil", varname)
1034 case reflect.Map:
1035
1036
1037
1038
1039
1040 x.linef("if %s == nil { r.EncodeNil() } else {", varname)
1041 tu, rtidu := genFastpathUnderlying(t, rtid, ti2)
1042 if fastpathAvIndex(rtidu) != -1 {
1043 g := x.newFastpathGenV(tu)
1044 if rtid == rtidu {
1045 x.linef("z.F.%sV(%s, e)", g.MethodNamePfx("Enc", false), varname)
1046 } else {
1047 x.linef("z.F.%sV((%s)(%s), e)", g.MethodNamePfx("Enc", false), x.genTypeName(tu), varname)
1048 }
1049 } else {
1050 x.xtraSM(varname, t, ti2, true, false)
1051 }
1052 x.linef("} // end block: if %s map == nil", varname)
1053 case reflect.Struct:
1054 if !inlist {
1055 delete(x.te, rtid)
1056 x.line("z.EncFallback(" + varname + ")")
1057 break
1058 }
1059 x.encStruct(varname, rtid, t)
1060 default:
1061 if rtidAdded {
1062 delete(x.te, rtid)
1063 }
1064 x.line("z.EncFallback(" + varname + ")")
1065 }
1066 }
1067
1068 func (x *genRunner) encZero(t reflect.Type) {
1069 switch t.Kind() {
1070 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1071 x.line("r.EncodeInt(0)")
1072 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1073 x.line("r.EncodeUint(0)")
1074 case reflect.Float32:
1075 x.line("r.EncodeFloat32(0)")
1076 case reflect.Float64:
1077 x.line("r.EncodeFloat64(0)")
1078 case reflect.Complex64:
1079 x.line("z.EncEncodeComplex64(0)")
1080 case reflect.Complex128:
1081 x.line("z.EncEncodeComplex128(0)")
1082 case reflect.Bool:
1083 x.line("r.EncodeBool(false)")
1084 case reflect.String:
1085 x.linef(`r.EncodeString("")`)
1086 default:
1087 x.line("r.EncodeNil()")
1088 }
1089 }
1090
1091 func genOmitEmptyLinePreChecks(varname string, t reflect.Type, si *structFieldInfo, omitline *genBuf, oneLevel bool) (t2 reflect.StructField) {
1092
1093 t2typ := t
1094 varname3 := varname
1095
1096
1097 fullpath := si.path.fullpath()
1098 for i, path := range fullpath {
1099 for t2typ.Kind() == reflect.Ptr {
1100 t2typ = t2typ.Elem()
1101 }
1102 t2 = t2typ.Field(int(path.index))
1103 t2typ = t2.Type
1104 varname3 = varname3 + "." + t2.Name
1105
1106
1107 if i+1 < len(fullpath) && t2typ.Kind() == reflect.Ptr {
1108 omitline.s(varname3).s(" != nil && ")
1109 }
1110 if oneLevel {
1111 break
1112 }
1113 }
1114 return
1115 }
1116
1117 func (x *genRunner) doEncOmitEmptyLine(t2 reflect.StructField, varname string, buf *genBuf) {
1118 x.f = 0
1119 x.encOmitEmptyLine(t2, varname, buf)
1120 }
1121
1122 func (x *genRunner) encOmitEmptyLine(t2 reflect.StructField, varname string, buf *genBuf) {
1123
1124
1125
1126 varname2 := varname + "." + t2.Name
1127 switch t2.Type.Kind() {
1128 case reflect.Struct:
1129 rtid2 := rt2id(t2.Type)
1130 ti2 := x.ti.get(rtid2, t2.Type)
1131
1132 if ti2.rtid == timeTypId {
1133 buf.s("!(").s(varname2).s(".IsZero())")
1134 break
1135 }
1136 if ti2.flagIsZeroerPtr || ti2.flagIsZeroer {
1137 buf.s("!(").s(varname2).s(".IsZero())")
1138 break
1139 }
1140 if t2.Type.Implements(isCodecEmptyerTyp) {
1141 buf.s("!(").s(varname2).s(".IsCodecEmpty())")
1142 break
1143 }
1144 _, ok := x.tz[rtid2]
1145 if ok {
1146 buf.s("!(").s(varname2).s(".IsCodecEmpty())")
1147 break
1148 }
1149
1150
1151 if genImportPath(t2.Type) == x.bp {
1152 x.ty[t2.Type] = struct{}{}
1153 buf.s("!(").s(varname2).s(".IsCodecEmpty())")
1154 break
1155 }
1156 if ti2.flagComparable {
1157 buf.s(varname2).s(" != ").s(x.genZeroValueR(t2.Type))
1158 break
1159 }
1160
1161 buf.s(x.sayFalse())
1162 var wrote bool
1163 for i, n := 0, t2.Type.NumField(); i < n; i++ {
1164 f := t2.Type.Field(i)
1165 if f.PkgPath != "" {
1166 continue
1167 }
1168 buf.s(" || ")
1169 x.encOmitEmptyLine(f, varname2, buf)
1170 wrote = true
1171 }
1172 if !wrote {
1173 buf.s(" || ").s(x.sayTrue())
1174 }
1175
1176 case reflect.Bool:
1177 buf.s("bool(").s(varname2).s(")")
1178 case reflect.Map, reflect.Slice, reflect.Chan:
1179 buf.s("len(").s(varname2).s(") != 0")
1180 case reflect.Array:
1181 tlen := t2.Type.Len()
1182 if tlen == 0 {
1183 buf.s(x.sayFalse())
1184 } else if t2.Type.Comparable() {
1185 buf.s(varname2).s(" != ").s(x.genZeroValueR(t2.Type))
1186 } else {
1187
1188
1189 buf.s(x.sayTrue())
1190 }
1191 default:
1192 buf.s(varname2).s(" != ").s(x.genZeroValueR(t2.Type))
1193 }
1194 }
1195
1196 func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
1197
1198
1199
1200
1201 ti := x.ti.get(rtid, t)
1202 i := x.varsfx()
1203
1204 numfieldsvar := genTempVarPfx + "q" + i
1205 ti2arrayvar := genTempVarPfx + "r" + i
1206 struct2arrvar := genTempVarPfx + "2arr" + i
1207
1208 tisfi := ti.sfi.source()
1209
1210 type genFQN struct {
1211 i string
1212 fqname string
1213 nilLine genBuf
1214 nilVar string
1215 canNil bool
1216 sf reflect.StructField
1217 }
1218
1219 genFQNs := make([]genFQN, len(tisfi))
1220 si2Pos := make(map[*structFieldInfo]int)
1221
1222 for j, si := range tisfi {
1223 si2Pos[si] = j
1224 q := &genFQNs[j]
1225 q.i = x.varsfx()
1226 q.nilVar = genTempVarPfx + "n" + q.i
1227 q.canNil = false
1228 q.fqname = varname
1229 {
1230 t2typ := t
1231 fullpath := si.path.fullpath()
1232 for _, path := range fullpath {
1233 for t2typ.Kind() == reflect.Ptr {
1234 t2typ = t2typ.Elem()
1235 }
1236 q.sf = t2typ.Field(int(path.index))
1237 t2typ = q.sf.Type
1238 q.fqname += "." + q.sf.Name
1239 if t2typ.Kind() == reflect.Ptr {
1240 if !q.canNil {
1241 q.nilLine.f("%s == nil", q.fqname)
1242 q.canNil = true
1243 } else {
1244 q.nilLine.f(" || %s == nil", q.fqname)
1245 }
1246 }
1247 }
1248 }
1249 }
1250
1251
1252 x.linef("%s := z.EncBasicHandle().StructToArray", struct2arrvar)
1253
1254 x.linef("_ = %s", struct2arrvar)
1255 x.linef("const %s bool = %v // struct tag has 'toArray'", ti2arrayvar, ti.toArray)
1256
1257 for j := range genFQNs {
1258 q := &genFQNs[j]
1259 if q.canNil {
1260 x.linef("var %s bool = %s", q.nilVar, q.nilLine.v())
1261 }
1262 }
1263
1264
1265
1266
1267
1268
1269 omitEmptySometimes := x.omitEmptyWhen == nil
1270 omitEmptyAlways := (x.omitEmptyWhen != nil && *(x.omitEmptyWhen))
1271
1272
1273 toArraySometimes := x.toArrayWhen == nil
1274 toArrayAlways := (x.toArrayWhen != nil && *(x.toArrayWhen))
1275 toArrayNever := (x.toArrayWhen != nil && !(*(x.toArrayWhen)))
1276
1277 if (omitEmptySometimes && ti.anyOmitEmpty) || omitEmptyAlways {
1278 x.linef("var %s = [%v]bool{ // should field at this index be written?", numfieldsvar, len(tisfi))
1279
1280 for _, si := range tisfi {
1281 if omitEmptySometimes && !si.path.omitEmpty {
1282 x.linef("true, // %s", si.encName)
1283 continue
1284 }
1285 var omitline genBuf
1286 t2 := genOmitEmptyLinePreChecks(varname, t, si, &omitline, false)
1287 x.doEncOmitEmptyLine(t2, varname, &omitline)
1288 x.linef("%s, // %s", omitline.v(), si.encName)
1289 }
1290 x.line("}")
1291 x.linef("_ = %s", numfieldsvar)
1292 }
1293
1294 if toArraySometimes {
1295 x.linef("if %s || %s {", ti2arrayvar, struct2arrvar)
1296 }
1297 if toArraySometimes || toArrayAlways {
1298 x.linef("z.EncWriteArrayStart(%d)", len(tisfi))
1299
1300 for j, si := range tisfi {
1301 doOmitEmptyCheck := (omitEmptySometimes && si.path.omitEmpty) || omitEmptyAlways
1302 q := &genFQNs[j]
1303
1304 if q.canNil {
1305 x.linef("if %s { z.EncWriteArrayElem(); r.EncodeNil() } else { ", q.nilVar)
1306 }
1307 x.linef("z.EncWriteArrayElem()")
1308 if doOmitEmptyCheck {
1309 x.linef("if %s[%v] {", numfieldsvar, j)
1310 }
1311 x.encVarChkNil(q.fqname, q.sf.Type, false)
1312 if doOmitEmptyCheck {
1313 x.linef("} else {")
1314 x.encZero(q.sf.Type)
1315 x.linef("}")
1316 }
1317 if q.canNil {
1318 x.line("}")
1319 }
1320 }
1321
1322 x.line("z.EncWriteArrayEnd()")
1323 }
1324 if toArraySometimes {
1325 x.linef("} else {")
1326 }
1327 if toArraySometimes || toArrayNever {
1328 if (omitEmptySometimes && ti.anyOmitEmpty) || omitEmptyAlways {
1329 x.linef("var %snn%s int", genTempVarPfx, i)
1330 x.linef("for _, b := range %s { if b { %snn%s++ } }", numfieldsvar, genTempVarPfx, i)
1331 x.linef("z.EncWriteMapStart(%snn%s)", genTempVarPfx, i)
1332 x.linef("%snn%s = %v", genTempVarPfx, i, 0)
1333 } else {
1334 x.linef("z.EncWriteMapStart(%d)", len(tisfi))
1335 }
1336
1337 fn := func(tisfi []*structFieldInfo) {
1338
1339 for _, si := range tisfi {
1340 pos := si2Pos[si]
1341 q := &genFQNs[pos]
1342 doOmitEmptyCheck := (omitEmptySometimes && si.path.omitEmpty) || omitEmptyAlways
1343 if doOmitEmptyCheck {
1344 x.linef("if %s[%v] {", numfieldsvar, pos)
1345 }
1346 x.linef("z.EncWriteMapElemKey()")
1347
1348
1349 switch ti.keyType {
1350 case valueTypeInt:
1351 x.linef("r.EncodeInt(z.M.Int(strconv.ParseInt(`%s`, 10, 64)))", si.encName)
1352 case valueTypeUint:
1353 x.linef("r.EncodeUint(z.M.Uint(strconv.ParseUint(`%s`, 10, 64)))", si.encName)
1354 case valueTypeFloat:
1355 x.linef("r.EncodeFloat64(z.M.Float(strconv.ParseFloat(`%s`, 64)))", si.encName)
1356 default:
1357 if x.jsonOnlyWhen == nil {
1358 if si.path.encNameAsciiAlphaNum {
1359 x.linef(`if z.IsJSONHandle() { z.EncWr().WriteStr("\"%s\"") } else { `, si.encName)
1360 }
1361 x.linef("r.EncodeString(`%s`)", si.encName)
1362 if si.path.encNameAsciiAlphaNum {
1363 x.linef("}")
1364 }
1365 } else if *(x.jsonOnlyWhen) {
1366 if si.path.encNameAsciiAlphaNum {
1367 x.linef(`z.EncWr().WriteStr("\"%s\"")`, si.encName)
1368 } else {
1369 x.linef("r.EncodeString(`%s`)", si.encName)
1370 }
1371 } else {
1372 x.linef("r.EncodeString(`%s`)", si.encName)
1373 }
1374 }
1375 x.line("z.EncWriteMapElemValue()")
1376 if q.canNil {
1377 x.line("if " + q.nilVar + " { r.EncodeNil() } else { ")
1378 x.encVarChkNil(q.fqname, q.sf.Type, false)
1379 x.line("}")
1380 } else {
1381 x.encVarChkNil(q.fqname, q.sf.Type, false)
1382 }
1383 if doOmitEmptyCheck {
1384 x.line("}")
1385 }
1386 }
1387 }
1388
1389 if genStructCanonical {
1390 x.linef("if z.EncBasicHandle().Canonical {")
1391 fn(ti.sfi.sorted())
1392 x.linef("} else {")
1393 fn(ti.sfi.source())
1394 x.linef("}")
1395 } else {
1396 fn(tisfi)
1397 }
1398
1399 x.line("z.EncWriteMapEnd()")
1400 }
1401 if toArraySometimes {
1402 x.linef("} ")
1403 }
1404 }
1405
1406 func (x *genRunner) encListFallback(varname string, t reflect.Type) {
1407 x.linef("if %s == nil { r.EncodeNil(); return }", varname)
1408 elemBytes := t.Elem().Kind() == reflect.Uint8
1409 if t.AssignableTo(uint8SliceTyp) {
1410 x.linef("r.EncodeStringBytesRaw([]byte(%s))", varname)
1411 return
1412 }
1413 if t.Kind() == reflect.Array && elemBytes {
1414 x.linef("r.EncodeStringBytesRaw(((*[%d]byte)(%s))[:])", t.Len(), varname)
1415 return
1416 }
1417 i := x.varsfx()
1418 if t.Kind() == reflect.Chan {
1419 type ts struct {
1420 Label, Chan, Slice, Sfx string
1421 }
1422 tm, err := template.New("").Parse(genEncChanTmpl)
1423 genCheckErr(err)
1424 x.linef("if %s == nil { r.EncodeNil() } else { ", varname)
1425 x.linef("var sch%s []%s", i, x.genTypeName(t.Elem()))
1426 err = tm.Execute(x.w, &ts{"Lsch" + i, varname, "sch" + i, i})
1427 genCheckErr(err)
1428 if elemBytes {
1429 x.linef("r.EncodeStringBytesRaw([]byte(%s))", "sch"+i)
1430 x.line("}")
1431 return
1432 }
1433 varname = "sch" + i
1434 }
1435
1436 x.line("z.EncWriteArrayStart(len(" + varname + "))")
1437
1438
1439
1440
1441
1442
1443 x.linef("for %sv%s := range %s {", genTempVarPfx, i, varname)
1444 x.linef("z.EncWriteArrayElem()")
1445 x.encVar(fmt.Sprintf("%s[%sv%s]", varname, genTempVarPfx, i), t.Elem())
1446 x.line("}")
1447
1448 x.line("z.EncWriteArrayEnd()")
1449 if t.Kind() == reflect.Chan {
1450 x.line("}")
1451 }
1452 }
1453
1454 func (x *genRunner) encMapFallback(varname string, t reflect.Type) {
1455 x.linef("if %s == nil { r.EncodeNil()", varname)
1456 x.line("} else if z.EncBasicHandle().Canonical {")
1457
1458
1459
1460
1461
1462
1463 tkey := t.Key()
1464 tkind := tkey.Kind()
1465
1466
1467
1468
1469
1470
1471
1472 predeclared := tkey.PkgPath() == "" && tkey.Name() != ""
1473
1474 canonSortKind := reflect.Invalid
1475 switch tkind {
1476 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1477 canonSortKind = reflect.Int64
1478 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
1479 canonSortKind = reflect.Uint64
1480 case reflect.Float32, reflect.Float64:
1481 canonSortKind = reflect.Float64
1482 case reflect.String:
1483 canonSortKind = reflect.String
1484 }
1485
1486 var i string = x.varsfx()
1487
1488 fnCanonNumBoolStrKind := func() {
1489 if !predeclared {
1490 x.linef("var %svv%s %s", genTempVarPfx, i, x.genTypeName(tkey))
1491 x.linef("%sencfn%s := z.EncFnGivenAddr(&%svv%s)", genTempVarPfx, i, genTempVarPfx, i)
1492 }
1493
1494 x.linef("%ss%s := make([]%s, 0, len(%s))", genTempVarPfx, i, canonSortKind, varname)
1495 x.linef("for k, _ := range %s {", varname)
1496 x.linef(" %ss%s = append(%ss%s, %s(k))", genTempVarPfx, i, genTempVarPfx, i, canonSortKind)
1497 x.linef("}")
1498 x.linef("sort.Sort(%s%sSlice(%ss%s))", x.hn, canonSortKind, genTempVarPfx, i)
1499 x.linef("z.EncWriteMapStart(len(%s))", varname)
1500 x.linef("for _, %sv%s := range %ss%s {", genTempVarPfx, i, genTempVarPfx, i)
1501 x.linef(" z.EncWriteMapElemKey()")
1502 if predeclared {
1503 switch tkind {
1504 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
1505 x.linef("r.EncodeInt(int64(%sv%s))", genTempVarPfx, i)
1506 case reflect.Int64:
1507 x.linef("r.EncodeInt(%sv%s)", genTempVarPfx, i)
1508 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr:
1509 x.linef("r.EncodeUint(%sv%s)", genTempVarPfx, i)
1510 case reflect.Uint64:
1511 x.linef("r.EncodeUint(uint64(%sv%s))", genTempVarPfx, i)
1512 case reflect.Float32:
1513 x.linef("r.EncodeFloat32(float32(%sv%s))", genTempVarPfx, i)
1514 case reflect.Float64:
1515 x.linef("r.EncodeFloat64(%sv%s)", genTempVarPfx, i)
1516 case reflect.String:
1517 x.linef("r.EncodeString(%sv%s)", genTempVarPfx, i)
1518 }
1519 } else {
1520 x.linef("%svv%s = %s(%sv%s)", genTempVarPfx, i, x.genTypeName(tkey), genTempVarPfx, i)
1521 x.linef("z.EncEncodeNumBoolStrKindGivenAddr(&%svv%s, %sencfn%s)", genTempVarPfx, i, genTempVarPfx, i)
1522 }
1523 x.linef(" z.EncWriteMapElemValue()")
1524 vname := genTempVarPfx + "e" + i
1525 if predeclared {
1526 x.linef("%s := %s[%s(%sv%s)]", vname, varname, x.genTypeName(tkey), genTempVarPfx, i)
1527 } else {
1528 x.linef("%s := %s[%svv%s]", vname, varname, genTempVarPfx, i)
1529 }
1530 x.encVar(vname, t.Elem())
1531 x.linef("}")
1532
1533 x.line("z.EncWriteMapEnd()")
1534
1535 }
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551 if canonSortKind != reflect.Invalid {
1552 fnCanonNumBoolStrKind()
1553 } else {
1554 x.linef("z.EncEncodeMapNonNil(%s)", varname)
1555 }
1556
1557 x.line("} else {")
1558
1559 x.linef("z.EncWriteMapStart(len(%s))", varname)
1560 x.linef("for %sk%s, %sv%s := range %s {", genTempVarPfx, i, genTempVarPfx, i, varname)
1561 x.linef("z.EncWriteMapElemKey()")
1562 x.encVar(genTempVarPfx+"k"+i, t.Key())
1563 x.line("z.EncWriteMapElemValue()")
1564 x.encVar(genTempVarPfx+"v"+i, t.Elem())
1565 x.line("}")
1566 x.line("z.EncWriteMapEnd()")
1567
1568 x.line("}")
1569 }
1570
1571 func (x *genRunner) decVarInitPtr(varname, nilvar string, t reflect.Type, si *structFieldInfo,
1572 newbuf, nilbuf *genBuf) (varname3 string, t2 reflect.StructField) {
1573
1574
1575 varname3 = varname
1576 t2typ := t
1577 t2kind := t2typ.Kind()
1578 var nilbufed bool
1579 if si != nil {
1580 fullpath := si.path.fullpath()
1581 for _, path := range fullpath {
1582
1583 if t2typ.Kind() == reflect.Ptr {
1584 t2typ = t2typ.Elem()
1585 }
1586 t2 = t2typ.Field(int(path.index))
1587 t2typ = t2.Type
1588 varname3 = varname3 + "." + t2.Name
1589 t2kind = t2typ.Kind()
1590 if t2kind != reflect.Ptr {
1591 continue
1592 }
1593 if newbuf != nil {
1594 if len(newbuf.buf) > 0 {
1595 newbuf.s("\n")
1596 }
1597 newbuf.f("if %s == nil { %s = new(%s) }", varname3, varname3, x.genTypeName(t2typ.Elem()))
1598 }
1599 if nilbuf != nil {
1600 if !nilbufed {
1601 nilbuf.s("if ").s(varname3).s(" != nil")
1602 nilbufed = true
1603 } else {
1604 nilbuf.s(" && ").s(varname3).s(" != nil")
1605 }
1606 }
1607 }
1608 }
1609 if nilbuf != nil {
1610 if nilbufed {
1611 nilbuf.s(" { ").s("// remove the if-true\n")
1612 }
1613 if nilvar != "" {
1614 nilbuf.s(nilvar).s(" = true")
1615 } else if tk := t2typ.Kind(); tk == reflect.Ptr {
1616 if strings.IndexByte(varname3, '.') != -1 || strings.IndexByte(varname3, '[') != -1 {
1617 nilbuf.s(varname3).s(" = nil")
1618 } else {
1619 nilbuf.s("*").s(varname3).s(" = ").s(x.genZeroValueR(t2typ.Elem()))
1620 }
1621 } else {
1622 nilbuf.s(varname3).s(" = ").s(x.genZeroValueR(t2typ))
1623 }
1624 if nilbufed {
1625 nilbuf.s("}")
1626 }
1627 }
1628 return
1629 }
1630
1631
1632 func (x *genRunner) decVarMain(varname, rand string, t reflect.Type, checkNotNil bool) {
1633
1634
1635
1636
1637
1638
1639 var varname2 string
1640 if t.Kind() != reflect.Ptr {
1641 if t.PkgPath() != "" || !x.decTryAssignPrimitive(varname, t, false) {
1642 x.dec(varname, t, false)
1643 }
1644 } else {
1645 if checkNotNil {
1646 x.linef("if %s == nil { %s = new(%s) }", varname, varname, x.genTypeName(t.Elem()))
1647 }
1648
1649
1650 var ptrPfx string
1651 for t = t.Elem(); t.Kind() == reflect.Ptr; t = t.Elem() {
1652 ptrPfx += "*"
1653 if checkNotNil {
1654 x.linef("if %s%s == nil { %s%s = new(%s)}", ptrPfx, varname, ptrPfx, varname, x.genTypeName(t))
1655 }
1656 }
1657
1658
1659 if ptrPfx == "" {
1660 x.dec(varname, t, true)
1661 } else {
1662 varname2 = genTempVarPfx + "z" + rand
1663 x.line(varname2 + " := " + ptrPfx + varname)
1664 x.dec(varname2, t, true)
1665 }
1666 }
1667 }
1668
1669
1670 func (x *genRunner) decVar(varname, nilvar string, t reflect.Type, canBeNil, checkNotNil bool) {
1671
1672
1673
1674
1675
1676
1677
1678
1679 i := x.varsfx()
1680 if t.Kind() == reflect.Ptr {
1681 var buf genBuf
1682 x.decVarInitPtr(varname, nilvar, t, nil, nil, &buf)
1683 x.linef("if r.TryNil() { %s } else {", buf.buf)
1684 x.decVarMain(varname, i, t, checkNotNil)
1685 x.line("} ")
1686 } else {
1687 x.decVarMain(varname, i, t, checkNotNil)
1688 }
1689 }
1690
1691
1692 func (x *genRunner) dec(varname string, t reflect.Type, isptr bool) {
1693
1694
1695
1696 rtid := rt2id(t)
1697 ti2 := x.ti.get(rtid, t)
1698
1699
1700
1701
1702
1703 mi := x.varsfx()
1704
1705 var hasIf genIfClause
1706 defer hasIf.end(x)
1707
1708 var ptrPfx, addrPfx string
1709 if isptr {
1710 ptrPfx = "*"
1711 } else {
1712 addrPfx = "&"
1713 }
1714 if t == timeTyp {
1715 x.linef("%s z.DecBasicHandle().TimeBuiltin() { %s%v = r.DecodeTime()", hasIf.c(false), ptrPfx, varname)
1716
1717 }
1718 if t == rawTyp {
1719 x.linef("%s %s%v = z.DecRaw()", hasIf.c(true), ptrPfx, varname)
1720 return
1721 }
1722
1723 if t == rawExtTyp {
1724 x.linef("%s r.DecodeExt(%s%v, 0, nil)", hasIf.c(true), addrPfx, varname)
1725 return
1726 }
1727
1728
1729
1730
1731
1732 if !x.nx && varname != genTopLevelVarName && t != genStringDecAsBytesTyp &&
1733 t != genStringDecZCTyp && genImportPath(t) != "" && t.Name() != "" {
1734
1735 yy := fmt.Sprintf("%sxt%s", genTempVarPfx, mi)
1736 x.linef("%s %s := z.Extension(%s); %s != nil { z.DecExtension(%s%s, %s) ", hasIf.c(false), yy, varname, yy, addrPfx, varname, yy)
1737 }
1738
1739 if x.checkForSelfer(t, varname) {
1740 if ti2.flagSelfer {
1741 x.linef("%s %s.CodecDecodeSelf(d)", hasIf.c(true), varname)
1742 return
1743 }
1744 if ti2.flagSelferPtr {
1745 x.linef("%s %s.CodecDecodeSelf(d)", hasIf.c(true), varname)
1746 return
1747 }
1748 if _, ok := x.td[rtid]; ok {
1749 x.linef("%s %s.CodecDecodeSelf(d)", hasIf.c(true), varname)
1750 return
1751 }
1752 }
1753
1754 inlist := false
1755 for _, t0 := range x.t {
1756 if t == t0 {
1757 inlist = true
1758 if x.checkForSelfer(t, varname) {
1759 x.linef("%s %s.CodecDecodeSelf(d)", hasIf.c(true), varname)
1760 return
1761 }
1762 break
1763 }
1764 }
1765
1766 var rtidAdded bool
1767 if t == x.tc {
1768 x.td[rtid] = true
1769 rtidAdded = true
1770 }
1771
1772 if ti2.flagBinaryUnmarshaler {
1773 x.linef("%s z.DecBinary() { z.DecBinaryUnmarshal(%s%v) ", hasIf.c(false), ptrPfx, varname)
1774 } else if ti2.flagBinaryUnmarshalerPtr {
1775 x.linef("%s z.DecBinary() { z.DecBinaryUnmarshal(%s%v) ", hasIf.c(false), addrPfx, varname)
1776 }
1777 if ti2.flagJsonUnmarshaler {
1778 x.linef("%s !z.DecBinary() && z.IsJSONHandle() { z.DecJSONUnmarshal(%s%v)", hasIf.c(false), ptrPfx, varname)
1779 } else if ti2.flagJsonUnmarshalerPtr {
1780 x.linef("%s !z.DecBinary() && z.IsJSONHandle() { z.DecJSONUnmarshal(%s%v)", hasIf.c(false), addrPfx, varname)
1781 } else if ti2.flagTextUnmarshaler {
1782 x.linef("%s !z.DecBinary() { z.DecTextUnmarshal(%s%v)", hasIf.c(false), ptrPfx, varname)
1783 } else if ti2.flagTextUnmarshalerPtr {
1784 x.linef("%s !z.DecBinary() { z.DecTextUnmarshal(%s%v)", hasIf.c(false), addrPfx, varname)
1785 }
1786
1787 x.lineIf(hasIf.c(true))
1788
1789 if x.decTryAssignPrimitive(varname, t, isptr) {
1790 return
1791 }
1792
1793 switch t.Kind() {
1794 case reflect.Chan:
1795 x.xtraSM(varname, t, ti2, false, isptr)
1796 case reflect.Array:
1797 _, rtidu := genFastpathUnderlying(t, rtid, ti2)
1798 if fastpathAvIndex(rtidu) != -1 {
1799 g := x.newFastpathGenV(ti2.key)
1800 x.linef("z.F.%sN((%s)(%s[:]), d)", g.MethodNamePfx("Dec", false), x.genTypeName(ti2.key), varname)
1801 } else {
1802 x.xtraSM(varname, t, ti2, false, isptr)
1803 }
1804 case reflect.Slice:
1805
1806
1807
1808
1809
1810
1811 if rtid == uint8SliceTypId {
1812 x.linef("%s%s = z.DecodeBytesInto(%s(%s[]byte)(%s))", ptrPfx, varname, ptrPfx, ptrPfx, varname)
1813 } else {
1814 tu, rtidu := genFastpathUnderlying(t, rtid, ti2)
1815 if fastpathAvIndex(rtidu) != -1 {
1816 g := x.newFastpathGenV(tu)
1817 if rtid == rtidu {
1818 x.linef("z.F.%sX(%s%s, d)", g.MethodNamePfx("Dec", false), addrPfx, varname)
1819 } else {
1820 x.linef("z.F.%sX((*%s)(%s%s), d)", g.MethodNamePfx("Dec", false), x.genTypeName(tu), addrPfx, varname)
1821 }
1822 } else {
1823 x.xtraSM(varname, t, ti2, false, isptr)
1824
1825 }
1826 }
1827 case reflect.Map:
1828
1829
1830
1831
1832
1833 tu, rtidu := genFastpathUnderlying(t, rtid, ti2)
1834 if fastpathAvIndex(rtidu) != -1 {
1835 g := x.newFastpathGenV(tu)
1836 if rtid == rtidu {
1837 x.linef("z.F.%sX(%s%s, d)", g.MethodNamePfx("Dec", false), addrPfx, varname)
1838 } else {
1839 x.linef("z.F.%sX((*%s)(%s%s), d)", g.MethodNamePfx("Dec", false), x.genTypeName(tu), addrPfx, varname)
1840 }
1841 } else {
1842 x.xtraSM(varname, t, ti2, false, isptr)
1843 }
1844 case reflect.Struct:
1845 if inlist {
1846
1847 if isptr || strings.IndexByte(varname, '.') != -1 || strings.IndexByte(varname, '[') != -1 {
1848 x.decStruct(varname, rtid, t)
1849 } else {
1850 varname2 := genTempVarPfx + "j" + mi
1851 x.line(varname2 + " := &" + varname)
1852 x.decStruct(varname2, rtid, t)
1853 }
1854 } else {
1855
1856 x.line("z.DecFallback(" + addrPfx + varname + ", false)")
1857 }
1858 default:
1859 if rtidAdded {
1860 delete(x.te, rtid)
1861 }
1862 x.line("z.DecFallback(" + addrPfx + varname + ", true)")
1863 }
1864 }
1865
1866 func (x *genRunner) decTryAssignPrimitive(varname string, t reflect.Type, isptr bool) (done bool) {
1867
1868
1869
1870
1871 var ptr string
1872 if isptr {
1873 ptr = "*"
1874 }
1875 switch t.Kind() {
1876 case reflect.Int:
1877 x.linef("%s%s = (%s)(z.C.IntV(r.DecodeInt64(), codecSelferBitsize%s))", ptr, varname, x.genTypeName(t), x.xs)
1878 case reflect.Int8:
1879 x.linef("%s%s = (%s)(z.C.IntV(r.DecodeInt64(), 8))", ptr, varname, x.genTypeName(t))
1880 case reflect.Int16:
1881 x.linef("%s%s = (%s)(z.C.IntV(r.DecodeInt64(), 16))", ptr, varname, x.genTypeName(t))
1882 case reflect.Int32:
1883 x.linef("%s%s = (%s)(z.C.IntV(r.DecodeInt64(), 32))", ptr, varname, x.genTypeName(t))
1884 case reflect.Int64:
1885 x.linef("%s%s = (%s)(r.DecodeInt64())", ptr, varname, x.genTypeName(t))
1886
1887 case reflect.Uint:
1888 x.linef("%s%s = (%s)(z.C.UintV(r.DecodeUint64(), codecSelferBitsize%s))", ptr, varname, x.genTypeName(t), x.xs)
1889 case reflect.Uint8:
1890 x.linef("%s%s = (%s)(z.C.UintV(r.DecodeUint64(), 8))", ptr, varname, x.genTypeName(t))
1891 case reflect.Uint16:
1892 x.linef("%s%s = (%s)(z.C.UintV(r.DecodeUint64(), 16))", ptr, varname, x.genTypeName(t))
1893 case reflect.Uint32:
1894 x.linef("%s%s = (%s)(z.C.UintV(r.DecodeUint64(), 32))", ptr, varname, x.genTypeName(t))
1895 case reflect.Uint64:
1896 x.linef("%s%s = (%s)(r.DecodeUint64())", ptr, varname, x.genTypeName(t))
1897 case reflect.Uintptr:
1898 x.linef("%s%s = (%s)(z.C.UintV(r.DecodeUint64(), codecSelferBitsize%s))", ptr, varname, x.genTypeName(t), x.xs)
1899
1900 case reflect.Float32:
1901 x.linef("%s%s = (%s)(z.DecDecodeFloat32())", ptr, varname, x.genTypeName(t))
1902 case reflect.Float64:
1903 x.linef("%s%s = (%s)(r.DecodeFloat64())", ptr, varname, x.genTypeName(t))
1904
1905 case reflect.Complex64:
1906 x.linef("%s%s = (%s)(complex(z.DecDecodeFloat32(), 0))", ptr, varname, x.genTypeName(t))
1907 case reflect.Complex128:
1908 x.linef("%s%s = (%s)(complex(r.DecodeFloat64(), 0))", ptr, varname, x.genTypeName(t))
1909
1910 case reflect.Bool:
1911 x.linef("%s%s = (%s)(r.DecodeBool())", ptr, varname, x.genTypeName(t))
1912 case reflect.String:
1913 if t == genStringDecAsBytesTyp {
1914 x.linef("%s%s = r.DecodeStringAsBytes()", ptr, varname)
1915 } else if t == genStringDecZCTyp {
1916 x.linef("%s%s = (string)(z.DecStringZC(r.DecodeStringAsBytes()))", ptr, varname)
1917 } else {
1918 x.linef("%s%s = (%s)(z.DecStringZC(r.DecodeStringAsBytes()))", ptr, varname, x.genTypeName(t))
1919 }
1920 default:
1921 return false
1922 }
1923 return true
1924 }
1925
1926 func (x *genRunner) decListFallback(varname string, rtid uintptr, t reflect.Type) {
1927 if t.AssignableTo(uint8SliceTyp) {
1928 x.line("*" + varname + " = z.DecodeBytesInto(*((*[]byte)(" + varname + ")))")
1929 return
1930 }
1931 if t.Kind() == reflect.Array && t.Elem().Kind() == reflect.Uint8 {
1932 x.linef("r.DecodeBytes( ((*[%d]byte)(%s))[:])", t.Len(), varname)
1933 return
1934 }
1935 type tstruc struct {
1936 TempVar string
1937 Sfx string
1938 Rand string
1939 Varname string
1940 CTyp string
1941 Typ string
1942 Immutable bool
1943 Size int
1944 }
1945 telem := t.Elem()
1946 ts := tstruc{genTempVarPfx, x.xs, x.varsfx(), varname, x.genTypeName(t), x.genTypeName(telem), genIsImmutable(telem), int(telem.Size())}
1947
1948 funcs := make(template.FuncMap)
1949
1950 funcs["decLineVar"] = func(varname string) string {
1951 x.decVar(varname, "", telem, false, true)
1952 return ""
1953 }
1954 funcs["var"] = func(s string) string {
1955 return ts.TempVar + s + ts.Rand
1956 }
1957 funcs["xs"] = func() string {
1958 return ts.Sfx
1959 }
1960 funcs["zero"] = func() string {
1961 return x.genZeroValueR(telem)
1962 }
1963 funcs["isArray"] = func() bool {
1964 return t.Kind() == reflect.Array
1965 }
1966 funcs["isSlice"] = func() bool {
1967 return t.Kind() == reflect.Slice
1968 }
1969 funcs["isChan"] = func() bool {
1970 return t.Kind() == reflect.Chan
1971 }
1972 tm, err := template.New("").Funcs(funcs).Parse(genDecListTmpl)
1973 genCheckErr(err)
1974 genCheckErr(tm.Execute(x.w, &ts))
1975 }
1976
1977 func (x *genRunner) decMapFallback(varname string, rtid uintptr, t reflect.Type) {
1978 type tstruc struct {
1979 TempVar string
1980 Sfx string
1981 Rand string
1982 Varname string
1983 KTyp string
1984 Typ string
1985 Size int
1986 }
1987 telem := t.Elem()
1988 tkey := t.Key()
1989 ts := tstruc{
1990 genTempVarPfx, x.xs, x.varsfx(), varname, x.genTypeName(tkey),
1991 x.genTypeName(telem), int(telem.Size() + tkey.Size()),
1992 }
1993
1994 funcs := make(template.FuncMap)
1995 funcs["decElemZero"] = func() string {
1996 return x.genZeroValueR(telem)
1997 }
1998 funcs["decElemKindImmutable"] = func() bool {
1999 return genIsImmutable(telem)
2000 }
2001 funcs["decElemKindPtr"] = func() bool {
2002 return telem.Kind() == reflect.Ptr
2003 }
2004 funcs["decElemKindIntf"] = func() bool {
2005 return telem.Kind() == reflect.Interface
2006 }
2007 funcs["decLineVarKStrBytes"] = func(varname string) string {
2008 x.decVar(varname, "", genStringDecAsBytesTyp, false, true)
2009 return ""
2010 }
2011 funcs["decLineVarKStrZC"] = func(varname string) string {
2012 x.decVar(varname, "", genStringDecZCTyp, false, true)
2013 return ""
2014 }
2015 funcs["decLineVarK"] = func(varname string) string {
2016 x.decVar(varname, "", tkey, false, true)
2017 return ""
2018 }
2019 funcs["decLineVar"] = func(varname, decodedNilVarname string) string {
2020 x.decVar(varname, decodedNilVarname, telem, false, true)
2021 return ""
2022 }
2023 funcs["var"] = func(s string) string {
2024 return ts.TempVar + s + ts.Rand
2025 }
2026 funcs["xs"] = func() string {
2027 return ts.Sfx
2028 }
2029
2030 tm, err := template.New("").Funcs(funcs).Parse(genDecMapTmpl)
2031 genCheckErr(err)
2032 genCheckErr(tm.Execute(x.w, &ts))
2033 }
2034
2035 func (x *genRunner) decStructMapSwitch(kName string, varname string, rtid uintptr, t reflect.Type) {
2036 ti := x.ti.get(rtid, t)
2037 tisfi := ti.sfi.source()
2038 x.line("switch string(" + kName + ") {")
2039 var newbuf, nilbuf genBuf
2040 for _, si := range tisfi {
2041 x.line("case \"" + si.encName + "\":")
2042 newbuf.reset()
2043 nilbuf.reset()
2044 varname3, t2 := x.decVarInitPtr(varname, "", t, si, &newbuf, &nilbuf)
2045 if len(newbuf.buf) > 0 {
2046 x.linef("if r.TryNil() { %s } else { %s", nilbuf.buf, newbuf.buf)
2047 }
2048 x.decVarMain(varname3, x.varsfx(), t2.Type, false)
2049 if len(newbuf.buf) > 0 {
2050 x.line("}")
2051 }
2052 }
2053 x.line("default:")
2054
2055 x.linef("z.DecStructFieldNotFound(-1, string(%s))", kName)
2056 x.linef("} // end switch %s", kName)
2057 }
2058
2059 func (x *genRunner) decStructMap(varname, lenvarname string, rtid uintptr, t reflect.Type) {
2060 tpfx := genTempVarPfx
2061 ti := x.ti.get(rtid, t)
2062 i := x.varsfx()
2063 kName := tpfx + "s" + i
2064
2065 x.linef("var %shl%s bool = %s >= 0", tpfx, i, lenvarname)
2066 x.linef("for %sj%s := 0; z.DecContainerNext(%sj%s, %s, %shl%s); %sj%s++ {",
2067 tpfx, i, tpfx, i, lenvarname, tpfx, i, tpfx, i)
2068
2069 x.line("z.DecReadMapElemKey()")
2070
2071
2072 switch ti.keyType {
2073 case valueTypeInt:
2074 x.linef("%s := strconv.AppendInt(z.DecScratchArrayBuffer()[:0], r.DecodeInt64(), 10)", kName)
2075 case valueTypeUint:
2076 x.linef("%s := strconv.AppendUint(z.DecScratchArrayBuffer()[:0], r.DecodeUint64(), 10)", kName)
2077 case valueTypeFloat:
2078 x.linef("%s := strconv.AppendFloat(z.DecScratchArrayBuffer()[:0], r.DecodeFloat64(), 'f', -1, 64)", kName)
2079 default:
2080 x.linef("%s := r.DecodeStringAsBytes()", kName)
2081 }
2082
2083 x.line("z.DecReadMapElemValue()")
2084 x.decStructMapSwitch(kName, varname, rtid, t)
2085
2086 x.line("} // end for " + tpfx + "j" + i)
2087 }
2088
2089 func (x *genRunner) decStructArray(varname, lenvarname, breakString string, rtid uintptr, t reflect.Type) {
2090 tpfx := genTempVarPfx
2091 i := x.varsfx()
2092 ti := x.ti.get(rtid, t)
2093 tisfi := ti.sfi.source()
2094 x.linef("var %sj%s int", tpfx, i)
2095 x.linef("var %sb%s bool", tpfx, i)
2096 x.linef("var %shl%s bool = %s >= 0", tpfx, i, lenvarname)
2097 var newbuf, nilbuf genBuf
2098 for _, si := range tisfi {
2099 x.linef("%sb%s = !z.DecContainerNext(%sj%s, %s, %shl%s)", tpfx, i, tpfx, i, lenvarname, tpfx, i)
2100 x.linef("if %sb%s { z.DecReadArrayEnd(); %s }", tpfx, i, breakString)
2101 x.line("z.DecReadArrayElem()")
2102 newbuf.reset()
2103 nilbuf.reset()
2104 varname3, t2 := x.decVarInitPtr(varname, "", t, si, &newbuf, &nilbuf)
2105 if len(newbuf.buf) > 0 {
2106 x.linef("if r.TryNil() { %s } else { %s", nilbuf.buf, newbuf.buf)
2107 }
2108 x.decVarMain(varname3, x.varsfx(), t2.Type, false)
2109 if len(newbuf.buf) > 0 {
2110 x.line("}")
2111 }
2112 x.linef("%sj%s++", tpfx, i)
2113 }
2114
2115 x.linef("for ; z.DecContainerNext(%sj%s, %s, %shl%s); %sj%s++ {",
2116 tpfx, i, lenvarname, tpfx, i, tpfx, i)
2117 x.line("z.DecReadArrayElem()")
2118 x.linef(`z.DecStructFieldNotFound(%sj%s - 1, "")`, tpfx, i)
2119 x.line("}")
2120 }
2121
2122 func (x *genRunner) decStruct(varname string, rtid uintptr, t reflect.Type) {
2123
2124 i := x.varsfx()
2125 x.linef("%sct%s := r.ContainerType()", genTempVarPfx, i)
2126 x.linef("if %sct%s == codecSelferValueTypeNil%s {", genTempVarPfx, i, x.xs)
2127 x.linef("*(%s) = %s{}", varname, x.genTypeName(t))
2128 x.linef("} else if %sct%s == codecSelferValueTypeMap%s {", genTempVarPfx, i, x.xs)
2129 x.line(genTempVarPfx + "l" + i + " := z.DecReadMapStart()")
2130 x.linef("if %sl%s == 0 {", genTempVarPfx, i)
2131
2132 x.line("} else { ")
2133 x.linef("%s.codecDecodeSelfFromMap(%sl%s, d)", varname, genTempVarPfx, i)
2134
2135 x.line("}")
2136 x.line("z.DecReadMapEnd()")
2137
2138
2139 x.linef("} else if %sct%s == codecSelferValueTypeArray%s {", genTempVarPfx, i, x.xs)
2140 x.line(genTempVarPfx + "l" + i + " := z.DecReadArrayStart()")
2141 x.linef("if %sl%s != 0 {", genTempVarPfx, i)
2142 x.linef("%s.codecDecodeSelfFromArray(%sl%s, d)", varname, genTempVarPfx, i)
2143 x.line("}")
2144 x.line("z.DecReadArrayEnd()")
2145
2146 x.line("} else { ")
2147 x.line("panic(errCodecSelferOnlyMapOrArrayEncodeToStruct" + x.xs + ")")
2148 x.line("} ")
2149 }
2150
2151
2152
2153 type fastpathGenV struct {
2154
2155 MapKey string
2156 Elem string
2157 Primitive string
2158 Size int
2159 NoCanonical bool
2160 }
2161
2162 func (x *genRunner) newFastpathGenV(t reflect.Type) (v fastpathGenV) {
2163 v.NoCanonical = !genFastpathCanonical
2164 switch t.Kind() {
2165 case reflect.Slice, reflect.Array:
2166 te := t.Elem()
2167 v.Elem = x.genTypeName(te)
2168 v.Size = int(te.Size())
2169 case reflect.Map:
2170 te := t.Elem()
2171 tk := t.Key()
2172 v.Elem = x.genTypeName(te)
2173 v.MapKey = x.genTypeName(tk)
2174 v.Size = int(te.Size() + tk.Size())
2175 default:
2176 halt.onerror(errGenUnexpectedTypeFastpath)
2177 }
2178 return
2179 }
2180
2181 func (x *fastpathGenV) MethodNamePfx(prefix string, prim bool) string {
2182 var name []byte
2183 if prefix != "" {
2184 name = append(name, prefix...)
2185 }
2186 if prim {
2187 name = append(name, genTitleCaseName(x.Primitive)...)
2188 } else {
2189 if x.MapKey == "" {
2190 name = append(name, "Slice"...)
2191 } else {
2192 name = append(name, "Map"...)
2193 name = append(name, genTitleCaseName(x.MapKey)...)
2194 }
2195 name = append(name, genTitleCaseName(x.Elem)...)
2196 }
2197 return string(name)
2198 }
2199
2200
2201
2202
2203
2204
2205 func genImportPath(t reflect.Type) (s string) {
2206 s = t.PkgPath()
2207 if genCheckVendor {
2208
2209 s = genStripVendor(s)
2210 }
2211 return
2212 }
2213
2214
2215 func genGoIdentifier(s string, checkFirstChar bool) string {
2216 b := make([]byte, 0, len(s))
2217 t := make([]byte, 4)
2218 var n int
2219 for i, r := range s {
2220 if checkFirstChar && i == 0 && !unicode.IsLetter(r) {
2221 b = append(b, '_')
2222 }
2223
2224 if unicode.IsLetter(r) || unicode.IsDigit(r) {
2225 n = utf8.EncodeRune(t, r)
2226 b = append(b, t[:n]...)
2227 } else {
2228 b = append(b, '_')
2229 }
2230 }
2231 return string(b)
2232 }
2233
2234 func genNonPtr(t reflect.Type) reflect.Type {
2235 for t.Kind() == reflect.Ptr {
2236 t = t.Elem()
2237 }
2238 return t
2239 }
2240
2241 func genFastpathUnderlying(t reflect.Type, rtid uintptr, ti *typeInfo) (tu reflect.Type, rtidu uintptr) {
2242 tu = t
2243 rtidu = rtid
2244 if ti.flagHasPkgPath {
2245 tu = ti.fastpathUnderlying
2246 rtidu = rt2id(tu)
2247 }
2248 return
2249 }
2250
2251 func genTitleCaseName(s string) string {
2252 switch s {
2253 case "interface{}", "interface {}":
2254 return "Intf"
2255 case "[]byte", "[]uint8", "bytes":
2256 return "Bytes"
2257 default:
2258 return strings.ToUpper(s[0:1]) + s[1:]
2259 }
2260 }
2261
2262 func genMethodNameT(t reflect.Type, tRef reflect.Type) (n string) {
2263 var ptrPfx string
2264 for t.Kind() == reflect.Ptr {
2265 ptrPfx += "Ptrto"
2266 t = t.Elem()
2267 }
2268 tstr := t.String()
2269 if tn := t.Name(); tn != "" {
2270 if tRef != nil && genImportPath(t) == genImportPath(tRef) {
2271 return ptrPfx + tn
2272 } else {
2273 if genQNameRegex.MatchString(tstr) {
2274 return ptrPfx + strings.Replace(tstr, ".", "_", 1000)
2275 } else {
2276 return ptrPfx + genCustomTypeName(tstr)
2277 }
2278 }
2279 }
2280 switch t.Kind() {
2281 case reflect.Map:
2282 return ptrPfx + "Map" + genMethodNameT(t.Key(), tRef) + genMethodNameT(t.Elem(), tRef)
2283 case reflect.Slice:
2284 return ptrPfx + "Slice" + genMethodNameT(t.Elem(), tRef)
2285 case reflect.Array:
2286 return ptrPfx + "Array" + strconv.FormatInt(int64(t.Len()), 10) + genMethodNameT(t.Elem(), tRef)
2287 case reflect.Chan:
2288 var cx string
2289 switch t.ChanDir() {
2290 case reflect.SendDir:
2291 cx = "ChanSend"
2292 case reflect.RecvDir:
2293 cx = "ChanRecv"
2294 default:
2295 cx = "Chan"
2296 }
2297 return ptrPfx + cx + genMethodNameT(t.Elem(), tRef)
2298 default:
2299 if t == intfTyp {
2300 return ptrPfx + "Interface"
2301 } else {
2302 if tRef != nil && genImportPath(t) == genImportPath(tRef) {
2303 if t.Name() != "" {
2304 return ptrPfx + t.Name()
2305 } else {
2306 return ptrPfx + genCustomTypeName(tstr)
2307 }
2308 } else {
2309
2310 if t.Name() != "" && genQNameRegex.MatchString(tstr) {
2311 return ptrPfx + strings.Replace(tstr, ".", "_", 1000)
2312 } else {
2313 return ptrPfx + genCustomTypeName(tstr)
2314 }
2315 }
2316 }
2317 }
2318 }
2319
2320
2321
2322 func genCustomTypeName(tstr string) string {
2323 len2 := genTypenameEnc.EncodedLen(len(tstr))
2324 bufx := make([]byte, len2)
2325 genTypenameEnc.Encode(bufx, []byte(tstr))
2326 for i := len2 - 1; i >= 0; i-- {
2327 if bufx[i] == '=' {
2328 len2--
2329 } else {
2330 break
2331 }
2332 }
2333 return string(bufx[:len2])
2334 }
2335
2336 func genIsImmutable(t reflect.Type) (v bool) {
2337 return scalarBitset.isset(byte(t.Kind()))
2338 }
2339
2340 type genInternal struct {
2341 Version int
2342 Values []fastpathGenV
2343 Formats []string
2344 }
2345
2346 func (x genInternal) FastpathLen() (l int) {
2347 for _, v := range x.Values {
2348
2349 if v.Primitive == "" {
2350 l++
2351 }
2352 }
2353 return
2354 }
2355
2356 func genInternalZeroValue(s string) string {
2357 switch s {
2358 case "interface{}", "interface {}":
2359 return "nil"
2360 case "[]byte", "[]uint8", "bytes":
2361 return "nil"
2362 case "bool":
2363 return "false"
2364 case "string":
2365 return `""`
2366 default:
2367 return "0"
2368 }
2369 }
2370
2371 var genInternalNonZeroValueIdx [6]uint64
2372 var genInternalNonZeroValueStrs = [...][6]string{
2373 {`"string-is-an-interface-1"`, "true", `"some-string-1"`, `[]byte("some-string-1")`, "11.1", "111"},
2374 {`"string-is-an-interface-2"`, "false", `"some-string-2"`, `[]byte("some-string-2")`, "22.2", "77"},
2375 {`"string-is-an-interface-3"`, "true", `"some-string-3"`, `[]byte("some-string-3")`, "33.3e3", "127"},
2376 }
2377
2378
2379
2380 func genInternalNonZeroValue(s string) string {
2381 var i int
2382 switch s {
2383 case "interface{}", "interface {}":
2384 i = 0
2385 case "bool":
2386 i = 1
2387 case "string":
2388 i = 2
2389 case "bytes", "[]byte", "[]uint8":
2390 i = 3
2391 case "float32", "float64", "float", "double", "complex", "complex64", "complex128":
2392 i = 4
2393 default:
2394 i = 5
2395 }
2396 genInternalNonZeroValueIdx[i]++
2397 idx := genInternalNonZeroValueIdx[i]
2398 slen := uint64(len(genInternalNonZeroValueStrs))
2399 return genInternalNonZeroValueStrs[idx%slen][i]
2400 }
2401
2402
2403 func genInternalEncCommandAsString(s string, vname string) string {
2404 switch s {
2405 case "uint64":
2406 return "e.e.EncodeUint(" + vname + ")"
2407 case "uint", "uint8", "uint16", "uint32":
2408 return "e.e.EncodeUint(uint64(" + vname + "))"
2409 case "int64":
2410 return "e.e.EncodeInt(" + vname + ")"
2411 case "int", "int8", "int16", "int32":
2412 return "e.e.EncodeInt(int64(" + vname + "))"
2413 case "[]byte", "[]uint8", "bytes":
2414 return "e.e.EncodeStringBytesRaw(" + vname + ")"
2415 case "string":
2416 return "e.e.EncodeString(" + vname + ")"
2417 case "float32":
2418 return "e.e.EncodeFloat32(" + vname + ")"
2419 case "float64":
2420 return "e.e.EncodeFloat64(" + vname + ")"
2421 case "bool":
2422 return "e.e.EncodeBool(" + vname + ")"
2423
2424
2425 default:
2426 return "e.encode(" + vname + ")"
2427 }
2428 }
2429
2430
2431 func genInternalDecCommandAsString(s string, mapkey bool) string {
2432 switch s {
2433 case "uint":
2434 return "uint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))"
2435 case "uint8":
2436 return "uint8(chkOvf.UintV(d.d.DecodeUint64(), 8))"
2437 case "uint16":
2438 return "uint16(chkOvf.UintV(d.d.DecodeUint64(), 16))"
2439 case "uint32":
2440 return "uint32(chkOvf.UintV(d.d.DecodeUint64(), 32))"
2441 case "uint64":
2442 return "d.d.DecodeUint64()"
2443 case "uintptr":
2444 return "uintptr(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))"
2445 case "int":
2446 return "int(chkOvf.IntV(d.d.DecodeInt64(), intBitsize))"
2447 case "int8":
2448 return "int8(chkOvf.IntV(d.d.DecodeInt64(), 8))"
2449 case "int16":
2450 return "int16(chkOvf.IntV(d.d.DecodeInt64(), 16))"
2451 case "int32":
2452 return "int32(chkOvf.IntV(d.d.DecodeInt64(), 32))"
2453 case "int64":
2454 return "d.d.DecodeInt64()"
2455
2456 case "string":
2457
2458
2459
2460
2461 return "d.stringZC(d.d.DecodeStringAsBytes())"
2462 case "[]byte", "[]uint8", "bytes":
2463 return "d.d.DecodeBytes([]byte{})"
2464 case "float32":
2465 return "float32(d.decodeFloat32())"
2466 case "float64":
2467 return "d.d.DecodeFloat64()"
2468 case "complex64":
2469 return "complex(d.decodeFloat32(), 0)"
2470 case "complex128":
2471 return "complex(d.d.DecodeFloat64(), 0)"
2472 case "bool":
2473 return "d.d.DecodeBool()"
2474 default:
2475 halt.onerror(errors.New("gen internal: unknown type for decode: " + s))
2476 }
2477 return ""
2478 }
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505 func genInternalSortType(s string, elem bool) string {
2506 if elem {
2507 return s
2508 }
2509 return s + "Slice"
2510 }
2511
2512
2513 func genStripVendor(s string) string {
2514
2515
2516 const vendorStart = "vendor/"
2517 const vendorInline = "/vendor/"
2518 if i := strings.LastIndex(s, vendorInline); i >= 0 {
2519 s = s[i+len(vendorInline):]
2520 } else if strings.HasPrefix(s, vendorStart) {
2521 s = s[len(vendorStart):]
2522 }
2523 return s
2524 }
2525
2526
2527 var genInternalV = genInternal{Version: genVersion}
2528 var genInternalTmplFuncs template.FuncMap
2529 var genInternalOnce sync.Once
2530
2531 func genInternalInit() {
2532 wordSizeBytes := int(intBitsize) / 8
2533
2534 typesizes := map[string]int{
2535 "interface{}": 2 * wordSizeBytes,
2536 "string": 2 * wordSizeBytes,
2537 "[]byte": 3 * wordSizeBytes,
2538 "uint": 1 * wordSizeBytes,
2539 "uint8": 1,
2540 "uint16": 2,
2541 "uint32": 4,
2542 "uint64": 8,
2543 "uintptr": 1 * wordSizeBytes,
2544 "int": 1 * wordSizeBytes,
2545 "int8": 1,
2546 "int16": 2,
2547 "int32": 4,
2548 "int64": 8,
2549 "float32": 4,
2550 "float64": 8,
2551 "complex64": 8,
2552 "complex128": 16,
2553 "bool": 1,
2554 }
2555
2556
2557
2558
2559 var types = [...]string{
2560 "interface{}",
2561 "string",
2562 "[]byte",
2563 "float32",
2564 "float64",
2565 "uint",
2566 "uint8",
2567 "uint16",
2568 "uint32",
2569 "uint64",
2570 "uintptr",
2571 "int",
2572 "int8",
2573 "int16",
2574 "int32",
2575 "int64",
2576 "bool",
2577 }
2578
2579 var primitivetypes, slicetypes, mapkeytypes, mapvaltypes []string
2580
2581 primitivetypes = types[:]
2582 slicetypes = types[:]
2583 mapkeytypes = types[:]
2584 mapvaltypes = types[:]
2585
2586 if genFastpathTrimTypes {
2587
2588
2589
2590 slicetypes = genInternalFastpathSliceTypes()
2591 mapkeytypes = genInternalFastpathMapKeyTypes()
2592 mapvaltypes = genInternalFastpathMapValueTypes()
2593 }
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606 var gt = genInternal{Version: genVersion, Formats: genFormats}
2607
2608
2609
2610 for _, s := range primitivetypes {
2611 gt.Values = append(gt.Values,
2612 fastpathGenV{Primitive: s, Size: typesizes[s], NoCanonical: !genFastpathCanonical})
2613 }
2614 for _, s := range slicetypes {
2615
2616
2617
2618 gt.Values = append(gt.Values,
2619 fastpathGenV{Elem: s, Size: typesizes[s], NoCanonical: !genFastpathCanonical})
2620 }
2621 for _, s := range mapkeytypes {
2622
2623
2624
2625
2626 for _, ms := range mapvaltypes {
2627 gt.Values = append(gt.Values,
2628 fastpathGenV{MapKey: s, Elem: ms, Size: typesizes[s] + typesizes[ms], NoCanonical: !genFastpathCanonical})
2629 }
2630 }
2631
2632 funcs := make(template.FuncMap)
2633
2634 funcs["encmd"] = genInternalEncCommandAsString
2635 funcs["decmd"] = genInternalDecCommandAsString
2636 funcs["zerocmd"] = genInternalZeroValue
2637 funcs["nonzerocmd"] = genInternalNonZeroValue
2638 funcs["hasprefix"] = strings.HasPrefix
2639 funcs["sorttype"] = genInternalSortType
2640
2641 genInternalV = gt
2642 genInternalTmplFuncs = funcs
2643 }
2644
2645
2646 func genInternalGoFile(r io.Reader, w io.Writer) (err error) {
2647 genInternalOnce.Do(genInternalInit)
2648
2649 gt := genInternalV
2650
2651 t := template.New("").Funcs(genInternalTmplFuncs)
2652
2653 tmplstr, err := ioutil.ReadAll(r)
2654 if err != nil {
2655 return
2656 }
2657
2658 if t, err = t.Parse(string(tmplstr)); err != nil {
2659 return
2660 }
2661
2662 var out bytes.Buffer
2663 err = t.Execute(&out, gt)
2664 if err != nil {
2665 return
2666 }
2667
2668 bout, err := format.Source(out.Bytes())
2669 if err != nil {
2670 w.Write(out.Bytes())
2671
2672 return
2673 }
2674 w.Write(bout)
2675 return
2676 }
2677
2678 func genInternalFastpathSliceTypes() []string {
2679 return []string{
2680 "interface{}",
2681 "string",
2682 "[]byte",
2683 "float32",
2684 "float64",
2685
2686
2687 "uint8",
2688
2689
2690 "uint64",
2691
2692 "int",
2693
2694
2695 "int32",
2696 "int64",
2697 "bool",
2698 }
2699 }
2700
2701 func genInternalFastpathMapKeyTypes() []string {
2702 return []string{
2703
2704 "string",
2705
2706
2707
2708
2709 "uint8",
2710
2711
2712 "uint64",
2713
2714 "int",
2715
2716
2717 "int32",
2718
2719
2720 }
2721 }
2722
2723 func genInternalFastpathMapValueTypes() []string {
2724 return []string{
2725 "interface{}",
2726 "string",
2727 "[]byte",
2728
2729 "uint8",
2730
2731
2732 "uint64",
2733
2734 "int",
2735
2736
2737 "int32",
2738
2739
2740 "float64",
2741 "bool",
2742 }
2743 }
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758 func genInternalSortableTypes() []string {
2759 return genInternalFastpathMapKeyTypes()
2760 }
2761
2762
2763
2764
2765
2766
2767 func genInternalSortablePlusTypes() []string {
2768 return []string{
2769 "string",
2770 "float64",
2771 "uint64",
2772
2773 "int64",
2774
2775 "time",
2776 "bytes",
2777 }
2778 }
2779
2780 func genTypeForShortName(s string) string {
2781 switch s {
2782 case "time":
2783 return "time.Time"
2784 case "bytes":
2785 return "[]byte"
2786 }
2787 return s
2788 }
2789
2790 func genArgs(args ...interface{}) map[string]interface{} {
2791 m := make(map[string]interface{}, len(args)/2)
2792 for i := 0; i < len(args); {
2793 m[args[i].(string)] = args[i+1]
2794 i += 2
2795 }
2796 return m
2797 }
2798
2799 func genEndsWith(s0 string, sn ...string) bool {
2800 for _, s := range sn {
2801 if strings.HasSuffix(s0, s) {
2802 return true
2803 }
2804 }
2805 return false
2806 }
2807
2808 func genCheckErr(err error) {
2809 halt.onerror(err)
2810 }
2811
2812 func genRunSortTmpl2Go(fnameIn, fnameOut string) {
2813 var err error
2814
2815 funcs := make(template.FuncMap)
2816 funcs["sortables"] = genInternalSortableTypes
2817 funcs["sortablesplus"] = genInternalSortablePlusTypes
2818 funcs["tshort"] = genTypeForShortName
2819 funcs["endswith"] = genEndsWith
2820 funcs["args"] = genArgs
2821
2822 t := template.New("").Funcs(funcs)
2823 fin, err := os.Open(fnameIn)
2824 genCheckErr(err)
2825 defer fin.Close()
2826 fout, err := os.Create(fnameOut)
2827 genCheckErr(err)
2828 defer fout.Close()
2829 tmplstr, err := ioutil.ReadAll(fin)
2830 genCheckErr(err)
2831 t, err = t.Parse(string(tmplstr))
2832 genCheckErr(err)
2833 var out bytes.Buffer
2834 err = t.Execute(&out, 0)
2835 genCheckErr(err)
2836 bout, err := format.Source(out.Bytes())
2837 if err != nil {
2838 fout.Write(out.Bytes())
2839 }
2840 genCheckErr(err)
2841
2842 _, err = fout.Write(bout)
2843 genCheckErr(err)
2844 }
2845
2846 func genRunTmpl2Go(fnameIn, fnameOut string) {
2847
2848 fin, err := os.Open(fnameIn)
2849 genCheckErr(err)
2850 defer fin.Close()
2851 fout, err := os.Create(fnameOut)
2852 genCheckErr(err)
2853 defer fout.Close()
2854 err = genInternalGoFile(fin, fout)
2855 genCheckErr(err)
2856 }
2857
2858
2859
2860
2861 func (path *structFieldInfoPathNode) root() *structFieldInfoPathNode {
2862 TOP:
2863 if path.parent != nil {
2864 path = path.parent
2865 goto TOP
2866 }
2867 return path
2868 }
2869
2870 func (path *structFieldInfoPathNode) fullpath() (p []*structFieldInfoPathNode) {
2871
2872
2873 d := path.depth()
2874 p = make([]*structFieldInfoPathNode, d)
2875 for d--; d >= 0; d-- {
2876 p[d] = path
2877 path = path.parent
2878 }
2879 return
2880 }
2881
View as plain text