fast-path.go.tmpl 16 KB

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