另客网go项目公用的代码库

fast-path.go.tmpl 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. // +build !notfastpath
  2. // Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
  3. // Use of this source code is governed by a MIT license found in the LICENSE file.
  4. // Code generated from fast-path.go.tmpl - DO NOT EDIT.
  5. package codec
  6. // Fast path functions try to create a fast path encode or decode implementation
  7. // for common maps and slices.
  8. //
  9. // We define the functions and register then in this single file
  10. // so as not to pollute the encode.go and decode.go, and create a dependency in there.
  11. // This file can be omitted without causing a build failure.
  12. //
  13. // The advantage of fast paths is:
  14. // - Many calls bypass reflection altogether
  15. //
  16. // Currently support
  17. // - slice of all builtin types,
  18. // - map of all builtin types to string or interface value
  19. // - symmetrical maps of all builtin types (e.g. str-str, uint8-uint8)
  20. // This should provide adequate "typical" implementations.
  21. //
  22. // Note that fast track decode functions must handle values for which an address cannot be obtained.
  23. // For example:
  24. // m2 := map[string]int{}
  25. // p2 := []interface{}{m2}
  26. // // decoding into p2 will bomb if fast track functions do not treat like unaddressable.
  27. //
  28. import (
  29. "reflect"
  30. "sort"
  31. )
  32. const fastpathEnabled = true
  33. const fastpathMapBySliceErrMsg = "mapBySlice requires even slice length, but got %v"
  34. type fastpathT struct {}
  35. var fastpathTV fastpathT
  36. type fastpathE struct {
  37. rtid uintptr
  38. rt reflect.Type
  39. encfn func(*Encoder, *codecFnInfo, reflect.Value)
  40. decfn func(*Decoder, *codecFnInfo, reflect.Value)
  41. }
  42. type fastpathA [{{ .FastpathLen }}]fastpathE
  43. func (x *fastpathA) index(rtid uintptr) int {
  44. // use binary search to grab the index (adapted from sort/search.go)
  45. // Note: we use goto (instead of for loop) so this can be inlined.
  46. // h, i, j := 0, 0, len(x)
  47. var h, i uint
  48. var j = uint(len(x))
  49. LOOP:
  50. if i < j {
  51. h = i + (j-i)/2
  52. if x[h].rtid < rtid {
  53. i = h + 1
  54. } else {
  55. j = h
  56. }
  57. goto LOOP
  58. }
  59. if i < uint(len(x)) && x[i].rtid == rtid {
  60. return int(i)
  61. }
  62. return -1
  63. }
  64. type fastpathAslice []fastpathE
  65. func (x fastpathAslice) Len() int { return len(x) }
  66. func (x fastpathAslice) Less(i, j int) bool { return x[uint(i)].rtid < x[uint(j)].rtid }
  67. func (x fastpathAslice) Swap(i, j int) { x[uint(i)], x[uint(j)] = x[uint(j)], x[uint(i)] }
  68. var fastpathAV fastpathA
  69. // due to possible initialization loop error, make fastpath in an init()
  70. func init() {
  71. var i uint = 0
  72. fn := func(v interface{},
  73. fe func(*Encoder, *codecFnInfo, reflect.Value),
  74. fd func(*Decoder, *codecFnInfo, reflect.Value)) {
  75. xrt := reflect.TypeOf(v)
  76. xptr := rt2id(xrt)
  77. fastpathAV[i] = fastpathE{xptr, xrt, fe, fd}
  78. i++
  79. }
  80. {{/* do not register []uint8 in fast-path */}}
  81. {{range .Values}}{{if not .Primitive}}{{if not .MapKey }}{{if ne .Elem "uint8"}}
  82. fn([]{{ .Elem }}(nil), (*Encoder).{{ .MethodNamePfx "fastpathEnc" false }}R, (*Decoder).{{ .MethodNamePfx "fastpathDec" false }}R){{end}}{{end}}{{end}}{{end}}
  83. {{range .Values}}{{if not .Primitive}}{{if .MapKey }}
  84. fn(map[{{ .MapKey }}]{{ .Elem }}(nil), (*Encoder).{{ .MethodNamePfx "fastpathEnc" false }}R, (*Decoder).{{ .MethodNamePfx "fastpathDec" false }}R){{end}}{{end}}{{end}}
  85. sort.Sort(fastpathAslice(fastpathAV[:]))
  86. }
  87. // -- encode
  88. // -- -- fast path type switch
  89. func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool {
  90. switch v := iv.(type) {
  91. {{range .Values}}{{if not .Primitive}}{{if not .MapKey }}{{if ne .Elem "uint8"}}
  92. case []{{ .Elem }}:
  93. fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
  94. case *[]{{ .Elem }}:
  95. fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, e){{/*
  96. */}}{{end}}{{end}}{{end}}{{end}}
  97. {{range .Values}}{{if not .Primitive}}{{if .MapKey }}
  98. case map[{{ .MapKey }}]{{ .Elem }}:
  99. fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
  100. case *map[{{ .MapKey }}]{{ .Elem }}:
  101. fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, e){{/*
  102. */}}{{end}}{{end}}{{end}}
  103. default:
  104. _ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
  105. return false
  106. }
  107. return true
  108. }
  109. {{/*
  110. **** removing this block, as they are never called directly ****
  111. **** removing this block, as they are never called directly ****
  112. func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool {
  113. switch v := iv.(type) {
  114. {{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
  115. case []{{ .Elem }}:
  116. fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
  117. case *[]{{ .Elem }}:
  118. fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, e)
  119. {{end}}{{end}}{{end}}
  120. default:
  121. _ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
  122. return false
  123. }
  124. return true
  125. }
  126. func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool {
  127. switch v := iv.(type) {
  128. {{range .Values}}{{if not .Primitive}}{{if .MapKey }}
  129. case map[{{ .MapKey }}]{{ .Elem }}:
  130. fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
  131. case *map[{{ .MapKey }}]{{ .Elem }}:
  132. fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, e)
  133. {{end}}{{end}}{{end}}
  134. default:
  135. _ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
  136. return false
  137. }
  138. return true
  139. }
  140. **** removing this block, as they are never called directly ****
  141. **** removing this block, as they are never called directly ****
  142. */}}
  143. // -- -- fast path functions
  144. {{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
  145. func (e *Encoder) {{ .MethodNamePfx "fastpathEnc" false }}R(f *codecFnInfo, rv reflect.Value) {
  146. if f.ti.mbs {
  147. fastpathTV.{{ .MethodNamePfx "EncAsMap" false }}V(rv2i(rv).([]{{ .Elem }}), e)
  148. } else {
  149. fastpathTV.{{ .MethodNamePfx "Enc" false }}V(rv2i(rv).([]{{ .Elem }}), e)
  150. }
  151. }
  152. func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v []{{ .Elem }}, e *Encoder) {
  153. if v == nil { e.e.EncodeNil(); return }
  154. ee, esep := e.e, e.hh.hasElemSeparators()
  155. ee.WriteArrayStart(len(v))
  156. if esep {
  157. for _, v2 := range v {
  158. ee.WriteArrayElem()
  159. {{ encmd .Elem "v2"}}
  160. }
  161. } else {
  162. for _, v2 := range v {
  163. {{ encmd .Elem "v2"}}
  164. }
  165. } {{/*
  166. for _, v2 := range v {
  167. if esep { ee.WriteArrayElem() }
  168. {{ encmd .Elem "v2"}}
  169. } */}}
  170. ee.WriteArrayEnd()
  171. }
  172. func (_ fastpathT) {{ .MethodNamePfx "EncAsMap" false }}V(v []{{ .Elem }}, e *Encoder) {
  173. ee, esep := e.e, e.hh.hasElemSeparators()
  174. if len(v)%2 == 1 {
  175. e.errorf(fastpathMapBySliceErrMsg, len(v))
  176. return
  177. }
  178. ee.WriteMapStart(len(v) / 2)
  179. if esep {
  180. for j, v2 := range v {
  181. if j%2 == 0 {
  182. ee.WriteMapElemKey()
  183. } else {
  184. ee.WriteMapElemValue()
  185. }
  186. {{ encmd .Elem "v2"}}
  187. }
  188. } else {
  189. for _, v2 := range v {
  190. {{ encmd .Elem "v2"}}
  191. }
  192. } {{/*
  193. for j, v2 := range v {
  194. if esep {
  195. if j%2 == 0 {
  196. ee.WriteMapElemKey()
  197. } else {
  198. ee.WriteMapElemValue()
  199. }
  200. }
  201. {{ encmd .Elem "v2"}}
  202. } */}}
  203. ee.WriteMapEnd()
  204. }
  205. {{end}}{{end}}{{end}}
  206. {{range .Values}}{{if not .Primitive}}{{if .MapKey }}
  207. func (e *Encoder) {{ .MethodNamePfx "fastpathEnc" false }}R(f *codecFnInfo, rv reflect.Value) {
  208. fastpathTV.{{ .MethodNamePfx "Enc" false }}V(rv2i(rv).(map[{{ .MapKey }}]{{ .Elem }}), e)
  209. }
  210. func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, e *Encoder) {
  211. if v == nil { e.e.EncodeNil(); return }
  212. ee, esep := e.e, e.hh.hasElemSeparators()
  213. ee.WriteMapStart(len(v))
  214. if e.h.Canonical {
  215. {{if eq .MapKey "interface{}"}}{{/* out of band
  216. */}}var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
  217. e2 := NewEncoderBytes(&mksv, e.hh)
  218. v2 := make([]bytesI, len(v))
  219. var i, l uint
  220. var vp *bytesI {{/* put loop variables outside. seems currently needed for better perf */}}
  221. for k2 := range v {
  222. l = uint(len(mksv))
  223. e2.MustEncode(k2)
  224. vp = &v2[i]
  225. vp.v = mksv[l:]
  226. vp.i = k2
  227. i++
  228. }
  229. sort.Sort(bytesISlice(v2))
  230. if esep {
  231. for j := range v2 {
  232. ee.WriteMapElemKey()
  233. e.asis(v2[j].v)
  234. ee.WriteMapElemValue()
  235. e.encode(v[v2[j].i])
  236. }
  237. } else {
  238. for j := range v2 {
  239. e.asis(v2[j].v)
  240. e.encode(v[v2[j].i])
  241. }
  242. } {{/*
  243. for j := range v2 {
  244. if esep { ee.WriteMapElemKey() }
  245. e.asis(v2[j].v)
  246. if esep { ee.WriteMapElemValue() }
  247. e.encode(v[v2[j].i])
  248. } */}} {{else}}{{ $x := sorttype .MapKey true}}v2 := make([]{{ $x }}, len(v))
  249. var i uint
  250. for k := range v {
  251. v2[i] = {{ $x }}(k)
  252. i++
  253. }
  254. sort.Sort({{ sorttype .MapKey false}}(v2))
  255. if esep {
  256. for _, k2 := range v2 {
  257. ee.WriteMapElemKey()
  258. {{if eq .MapKey "string"}}ee.EncodeStringEnc(cUTF8, k2){{else}}{{ $y := printf "%s(k2)" .MapKey }}{{ encmd .MapKey $y }}{{end}}
  259. ee.WriteMapElemValue()
  260. {{ $y := printf "v[%s(k2)]" .MapKey }}{{ encmd .Elem $y }}
  261. }
  262. } else {
  263. for _, k2 := range v2 {
  264. {{if eq .MapKey "string"}}ee.EncodeStringEnc(cUTF8, k2){{else}}{{ $y := printf "%s(k2)" .MapKey }}{{ encmd .MapKey $y }}{{end}}
  265. {{ $y := printf "v[%s(k2)]" .MapKey }}{{ encmd .Elem $y }}
  266. }
  267. } {{/*
  268. for _, k2 := range v2 {
  269. if esep { ee.WriteMapElemKey() }
  270. {{if eq .MapKey "string"}}ee.EncodeStringEnc(cUTF8, k2){{else}}{{ $y := printf "%s(k2)" .MapKey }}{{ encmd .MapKey $y }}{{end}}
  271. if esep { ee.WriteMapElemValue() }
  272. {{ $y := printf "v[%s(k2)]" .MapKey }}{{ encmd .Elem $y }}
  273. } */}} {{end}}
  274. } else {
  275. if esep {
  276. for k2, v2 := range v {
  277. ee.WriteMapElemKey()
  278. {{if eq .MapKey "string"}}ee.EncodeStringEnc(cUTF8, k2){{else}}{{ encmd .MapKey "k2"}}{{end}}
  279. ee.WriteMapElemValue()
  280. {{ encmd .Elem "v2"}}
  281. }
  282. } else {
  283. for k2, v2 := range v {
  284. {{if eq .MapKey "string"}}ee.EncodeStringEnc(cUTF8, k2){{else}}{{ encmd .MapKey "k2"}}{{end}}
  285. {{ encmd .Elem "v2"}}
  286. }
  287. } {{/*
  288. for k2, v2 := range v {
  289. if esep { ee.WriteMapElemKey() }
  290. {{if eq .MapKey "string"}}ee.EncodeStringEnc(cUTF8, k2){{else}}{{ encmd .MapKey "k2"}}{{end}}
  291. if esep { ee.WriteMapElemValue() }
  292. {{ encmd .Elem "v2"}}
  293. } */}}
  294. }
  295. ee.WriteMapEnd()
  296. }
  297. {{end}}{{end}}{{end}}
  298. // -- decode
  299. // -- -- fast path type switch
  300. func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool {
  301. var changed bool
  302. switch v := iv.(type) {
  303. {{range .Values}}{{if not .Primitive}}{{if not .MapKey }}{{if ne .Elem "uint8"}}
  304. case []{{ .Elem }}:
  305. var v2 []{{ .Elem }}
  306. v2, changed = fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, false, d)
  307. if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
  308. copy(v, v2)
  309. }
  310. case *[]{{ .Elem }}:
  311. var v2 []{{ .Elem }}
  312. v2, changed = fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*v, true, d)
  313. if changed {
  314. *v = v2
  315. }{{/*
  316. */}}{{end}}{{end}}{{end}}{{end}}
  317. {{range .Values}}{{if not .Primitive}}{{if .MapKey }}{{/*
  318. // maps only change if nil, and in that case, there's no point copying
  319. */}}
  320. case map[{{ .MapKey }}]{{ .Elem }}:
  321. fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, false, d)
  322. case *map[{{ .MapKey }}]{{ .Elem }}:
  323. var v2 map[{{ .MapKey }}]{{ .Elem }}
  324. v2, changed = fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*v, true, d)
  325. if changed {
  326. *v = v2
  327. }{{/*
  328. */}}{{end}}{{end}}{{end}}
  329. default:
  330. _ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
  331. return false
  332. }
  333. return true
  334. }
  335. func fastpathDecodeSetZeroTypeSwitch(iv interface{}) bool {
  336. switch v := iv.(type) {
  337. {{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
  338. case *[]{{ .Elem }}:
  339. *v = nil {{/*
  340. */}}{{end}}{{end}}{{end}}
  341. {{range .Values}}{{if not .Primitive}}{{if .MapKey }}
  342. case *map[{{ .MapKey }}]{{ .Elem }}:
  343. *v = nil {{/*
  344. */}}{{end}}{{end}}{{end}}
  345. default:
  346. _ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
  347. return false
  348. }
  349. return true
  350. }
  351. // -- -- fast path functions
  352. {{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
  353. {{/*
  354. Slices can change if they
  355. - did not come from an array
  356. - are addressable (from a ptr)
  357. - are settable (e.g. contained in an interface{})
  358. */}}
  359. func (d *Decoder) {{ .MethodNamePfx "fastpathDec" false }}R(f *codecFnInfo, rv reflect.Value) {
  360. if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
  361. vp := rv2i(rv).(*[]{{ .Elem }})
  362. v, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*vp, !array, d)
  363. if changed { *vp = v }
  364. } else {
  365. v := rv2i(rv).([]{{ .Elem }})
  366. v2, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, !array, d)
  367. if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
  368. copy(v, v2)
  369. }
  370. }
  371. }
  372. func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *[]{{ .Elem }}, d *Decoder) {
  373. v, changed := f.{{ .MethodNamePfx "Dec" false }}V(*vp, true, d)
  374. if changed { *vp = v }
  375. }
  376. func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v []{{ .Elem }}, canChange bool, d *Decoder) (_ []{{ .Elem }}, changed bool) {
  377. dd := d.d{{/*
  378. // if dd.isContainerType(valueTypeNil) { dd.TryDecodeAsNil()
  379. */}}
  380. slh, containerLenS := d.decSliceHelperStart()
  381. if containerLenS == 0 {
  382. if canChange {
  383. if v == nil { v = []{{ .Elem }}{} } else if len(v) != 0 { v = v[:0] }
  384. changed = true
  385. }
  386. slh.End()
  387. return v, changed
  388. }
  389. d.depthIncr()
  390. hasLen := containerLenS > 0
  391. var xlen int
  392. if hasLen && canChange {
  393. if containerLenS > cap(v) {
  394. xlen = decInferLen(containerLenS, d.h.MaxInitLen, {{ .Size }})
  395. if xlen <= cap(v) {
  396. v = v[:uint(xlen)]
  397. } else {
  398. v = make([]{{ .Elem }}, uint(xlen))
  399. }
  400. changed = true
  401. } else if containerLenS != len(v) {
  402. v = v[:containerLenS]
  403. changed = true
  404. }
  405. }
  406. var j int
  407. for j = 0; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
  408. if j == 0 && len(v) == 0 && canChange {
  409. if hasLen {
  410. xlen = decInferLen(containerLenS, d.h.MaxInitLen, {{ .Size }})
  411. } else {
  412. xlen = 8
  413. }
  414. v = make([]{{ .Elem }}, uint(xlen))
  415. changed = true
  416. }
  417. // if indefinite, etc, then expand the slice if necessary
  418. var decodeIntoBlank bool
  419. if j >= len(v) {
  420. if canChange {
  421. v = append(v, {{ zerocmd .Elem }})
  422. changed = true
  423. } else {
  424. d.arrayCannotExpand(len(v), j+1)
  425. decodeIntoBlank = true
  426. }
  427. }
  428. slh.ElemContainerState(j)
  429. if decodeIntoBlank {
  430. d.swallow()
  431. } else if dd.TryDecodeAsNil() {
  432. v[uint(j)] = {{ zerocmd .Elem }}
  433. } else {
  434. {{ if eq .Elem "interface{}" }}d.decode(&v[uint(j)]){{ else }}v[uint(j)] = {{ decmd .Elem }}{{ end }}
  435. }
  436. }
  437. if canChange {
  438. if j < len(v) {
  439. v = v[:uint(j)]
  440. changed = true
  441. } else if j == 0 && v == nil {
  442. v = make([]{{ .Elem }}, 0)
  443. changed = true
  444. }
  445. }
  446. slh.End()
  447. d.depthDecr()
  448. return v, changed
  449. }
  450. {{end}}{{end}}{{end}}
  451. {{range .Values}}{{if not .Primitive}}{{if .MapKey }}
  452. {{/*
  453. Maps can change if they are
  454. - addressable (from a ptr)
  455. - settable (e.g. contained in an interface{})
  456. */}}
  457. func (d *Decoder) {{ .MethodNamePfx "fastpathDec" false }}R(f *codecFnInfo, rv reflect.Value) {
  458. if rv.Kind() == reflect.Ptr {
  459. vp := rv2i(rv).(*map[{{ .MapKey }}]{{ .Elem }})
  460. v, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*vp, true, d);
  461. if changed { *vp = v }
  462. } else {
  463. fastpathTV.{{ .MethodNamePfx "Dec" false }}V(rv2i(rv).(map[{{ .MapKey }}]{{ .Elem }}), false, d)
  464. }
  465. }
  466. func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *map[{{ .MapKey }}]{{ .Elem }}, d *Decoder) {
  467. v, changed := f.{{ .MethodNamePfx "Dec" false }}V(*vp, true, d)
  468. if changed { *vp = v }
  469. }
  470. func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, canChange bool,
  471. d *Decoder) (_ map[{{ .MapKey }}]{{ .Elem }}, changed bool) {
  472. dd, esep := d.d, d.hh.hasElemSeparators(){{/*
  473. // if dd.isContainerType(valueTypeNil) {dd.TryDecodeAsNil()
  474. */}}
  475. containerLen := dd.ReadMapStart()
  476. if canChange && v == nil {
  477. xlen := decInferLen(containerLen, d.h.MaxInitLen, {{ .Size }})
  478. v = make(map[{{ .MapKey }}]{{ .Elem }}, xlen)
  479. changed = true
  480. }
  481. if containerLen == 0 {
  482. dd.ReadMapEnd()
  483. return v, changed
  484. }
  485. d.depthIncr()
  486. {{ if eq .Elem "interface{}" }}mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
  487. {{end}}var mk {{ .MapKey }}
  488. var mv {{ .Elem }}
  489. hasLen := containerLen > 0
  490. for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
  491. if esep { dd.ReadMapElemKey() }
  492. {{ if eq .MapKey "interface{}" }}mk = nil
  493. d.decode(&mk)
  494. if bv, bok := mk.([]byte); bok {
  495. mk = d.string(bv) {{/* // maps cannot have []byte as key. switch to string. */}}
  496. }{{ else }}mk = {{ decmd .MapKey }}{{ end }}
  497. if esep { dd.ReadMapElemValue() }
  498. if dd.TryDecodeAsNil() {
  499. if v == nil {} else if d.h.DeleteOnNilMapValue { delete(v, mk) } else { v[mk] = {{ zerocmd .Elem }} }
  500. continue
  501. }
  502. {{ if eq .Elem "interface{}" }}if mapGet { mv = v[mk] } else { mv = nil }
  503. d.decode(&mv){{ else }}mv = {{ decmd .Elem }}{{ end }}
  504. if v != nil { v[mk] = mv }
  505. }
  506. dd.ReadMapEnd()
  507. d.depthDecr()
  508. return v, changed
  509. }
  510. {{end}}{{end}}{{end}}