//go:build !notfastpath && !codec.notfastpath // Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved. // Use of this source code is governed by a MIT license found in the LICENSE file. // Code generated from fastpath.go.tmpl - DO NOT EDIT. package codec // Fast path functions try to create a fast path encode or decode implementation // for common maps and slices. // // We define the functions and register them in this single file // so as not to pollute the encode.go and decode.go, and create a dependency in there. // This file can be omitted without causing a build failure. // // The advantage of fast paths is: // - Many calls bypass reflection altogether // // Currently support // - slice of all builtin types (numeric, bool, string, []byte) // - maps of builtin types to builtin or interface{} type, EXCEPT FOR // keys of type uintptr, int8/16/32, uint16/32, float32/64, bool, interface{} // AND values of type type int8/16/32, uint16/32 // This should provide adequate "typical" implementations. // // Note that fast track decode functions must handle values for which an address cannot be obtained. // For example: // m2 := map[string]int{} // p2 := []interface{}{m2} // // decoding into p2 will bomb if fast track functions do not treat like unaddressable. // {{/* // ---------------- fastpathEncMapR func (mapped to type id), routes to: - ft.EncMapV fastpathEncSliceR func (mapped to type id), delegates to one of: - ft.EncSliceV - ft.EncAsMapSliceV (when mapbyslice ie f.ti.mbs=true) // ---------------- fastpathDecSliceR func (mapped to type id), delegates to: - ft.DecSliceIntfY (when slice CAN be updated) - ft.DecSliceIntfN (when slice CANNOT be updated e.g. from array or non-addressable slice) fastpathDecMapR func (mapped to type id), routes to - ft.DecMapL (handles ptr which is changeable, and non-pointer which cannot be made if nil) // ---------------- NOTE: - fastpath typeswitch directly calls the secondary methods for builtin maps/slices with appropriate nil handling: - except EncAsMapSliceV which only applies to wrapper types not those in the switch - fastpathEncXXX functions mapped to type ID MUST do nil-checks during encode - they are only called by decodeValue/encodeValue or other code (same way kMap et al are called) */ -}} import ( "reflect" "sort" "slices" ) const fastpathEnabled = true {{/* const fastpathMapBySliceErrMsg = "mapBySlice requires even slice length, but got %v" */ -}} type fastpathARtid [{{ .FastpathLen }}]uintptr type fastpathRtRtid struct { rtid uintptr rt reflect.Type } type fastpathARtRtid [{{ .FastpathLen }}]fastpathRtRtid var ( fastpathAvRtidArr fastpathARtid fastpathAvRtRtidArr fastpathARtRtid fastpathAvRtid = fastpathAvRtidArr[:] fastpathAvRtRtid = fastpathAvRtRtidArr[:] ) func fastpathAvIndex(rtid uintptr) (i uint, ok bool) { return searchRtids(fastpathAvRtid, rtid) } func init() { var i uint = 0 fn := func(v interface{}) { xrt := reflect.TypeOf(v) xrtid := rt2id(xrt) xptrtid := rt2id(reflect.PointerTo(xrt)) {{- /* only the base slice/map rtid is put in fastpathAvIndex, since we only handle slices/map/array */}} fastpathAvRtid[i] = xrtid fastpathAvRtRtid[i] = fastpathRtRtid{ rtid: xrtid, rt: xrt } {{- /* fastpath type switches however handle slices/map/array, and pointers to them */}} encBuiltinRtids = append(encBuiltinRtids, xrtid, xptrtid) decBuiltinRtids = append(decBuiltinRtids, xrtid, xptrtid) i++ } {{/* do not register []byte in fastpath */}} {{range .Values}}{{if not .Primitive}}{{if not .MapKey -}} fn([]{{ .Elem }}(nil)) {{end}}{{end}}{{end}} {{range .Values}}{{if not .Primitive}}{{if .MapKey -}} fn(map[{{ .MapKey }}]{{ .Elem }}(nil)) {{end}}{{end}}{{end}} sort.Slice(fastpathAvRtid, func(i, j int) bool { return fastpathAvRtid[i] < fastpathAvRtid[j] }) sort.Slice(fastpathAvRtRtid, func(i, j int) bool { return fastpathAvRtRtid[i].rtid < fastpathAvRtRtid[j].rtid }) slices.Sort(encBuiltinRtids) slices.Sort(decBuiltinRtids) } func fastpathDecodeSetZeroTypeSwitch(iv interface{}) bool { switch v := iv.(type) { {{range .Values}}{{if not .Primitive}}{{if not .MapKey -}} case *[]{{ .Elem }}: *v = nil {{end}}{{end}}{{end}} {{range .Values}}{{if not .Primitive}}{{if .MapKey -}} case *map[{{ .MapKey }}]{{ .Elem }}: *v = nil {{end}}{{end}}{{end}} default: _ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4 return false } return true }