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