fast-path.go.tmpl 17 KB

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