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