mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-02 20:02:25 -06:00 
			
		
		
		
	* start fixing up tests * fix up tests + automate with drone * fiddle with linting * messing about with drone.yml * some more fiddling * hmmm * add cache * add vendor directory * verbose * ci updates * update some little things * update sig
		
			
				
	
	
		
			555 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			Cheetah
		
	
	
	
	
	
			
		
		
	
	
			555 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			Cheetah
		
	
	
	
	
	
// +build !notfastpath
 | 
						|
// +build !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 fast-path.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.
 | 
						|
// 
 | 
						|
 | 
						|
{{/*
 | 
						|
fastpathEncMapStringUint64R  (called by fastpath...switch)
 | 
						|
EncMapStringUint64V (called by codecgen)
 | 
						|
 | 
						|
fastpathEncSliceBoolR: (called by fastpath...switch) (checks f.ti.mbs and calls one of them below)
 | 
						|
EncSliceBoolV  (also called by codecgen)
 | 
						|
EncAsMapSliceBoolV (delegate when mapbyslice=true)
 | 
						|
 | 
						|
fastpathDecSliceIntfR (called by fastpath...switch) (calls Y or N below depending on if it can be updated)
 | 
						|
DecSliceIntfX  (called by codecgen) (calls Y below)
 | 
						|
DecSliceIntfY  (delegate when slice CAN be updated)
 | 
						|
DecSliceIntfN  (delegate when slice CANNOT be updated e.g. from array or non-addressable slice)
 | 
						|
 | 
						|
fastpathDecMap...R (called by fastpath...switch) (calls L or X? below)
 | 
						|
DecMap...X  (called by codecgen)
 | 
						|
DecMap...L  (delegated to by both above)
 | 
						|
*/ -}}
 | 
						|
 | 
						|
import (
 | 
						|
	"reflect"
 | 
						|
	"sort"
 | 
						|
)
 | 
						|
 | 
						|
const fastpathEnabled = true
 | 
						|
 | 
						|
{{/*
 | 
						|
const fastpathMapBySliceErrMsg = "mapBySlice requires even slice length, but got %v"
 | 
						|
*/ -}}
 | 
						|
 | 
						|
type fastpathT struct {}
 | 
						|
 | 
						|
var fastpathTV fastpathT
 | 
						|
 | 
						|
type fastpathE struct {
 | 
						|
	{{/* rtid uintptr */ -}}
 | 
						|
	rt reflect.Type 
 | 
						|
	encfn func(*Encoder, *codecFnInfo, reflect.Value)
 | 
						|
	decfn func(*Decoder, *codecFnInfo, reflect.Value)
 | 
						|
}
 | 
						|
 | 
						|
type fastpathA [{{ .FastpathLen }}]fastpathE
 | 
						|
type fastpathARtid [{{ .FastpathLen }}]uintptr
 | 
						|
 | 
						|
var fastpathAv fastpathA
 | 
						|
var fastpathAvRtid fastpathARtid
 | 
						|
 | 
						|
type fastpathAslice struct{}
 | 
						|
 | 
						|
func (fastpathAslice) Len() int { return {{ .FastpathLen }} }
 | 
						|
func (fastpathAslice) Less(i, j int) bool {
 | 
						|
	return fastpathAvRtid[uint(i)] < fastpathAvRtid[uint(j)]
 | 
						|
}
 | 
						|
func (fastpathAslice) Swap(i, j int) {
 | 
						|
	fastpathAvRtid[uint(i)], fastpathAvRtid[uint(j)] = fastpathAvRtid[uint(j)], fastpathAvRtid[uint(i)]
 | 
						|
	fastpathAv[uint(i)], fastpathAv[uint(j)] = fastpathAv[uint(j)], fastpathAv[uint(i)]
 | 
						|
}
 | 
						|
 | 
						|
func fastpathAvIndex(rtid uintptr) int {
 | 
						|
	// use binary search to grab the index (adapted from sort/search.go)
 | 
						|
	// Note: we use goto (instead of for loop) so this can be inlined.
 | 
						|
 	// h, i, j := 0, 0, {{ .FastpathLen }}
 | 
						|
	var h, i uint
 | 
						|
	var j uint = {{ .FastpathLen }}
 | 
						|
LOOP:
 | 
						|
	if i < j {
 | 
						|
		h = (i + j) >> 1 // avoid overflow when computing h // h = i + (j-i)/2
 | 
						|
		if fastpathAvRtid[h] < rtid {
 | 
						|
			i = h + 1
 | 
						|
		} else {
 | 
						|
			j = h
 | 
						|
		}
 | 
						|
		goto LOOP
 | 
						|
	}
 | 
						|
	if i < {{ .FastpathLen }} && fastpathAvRtid[i] == rtid {
 | 
						|
		return int(i)
 | 
						|
	}
 | 
						|
	return -1
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// due to possible initialization loop error, make fastpath in an init()
 | 
						|
func init() {
 | 
						|
	var i uint = 0
 | 
						|
	fn := func(v interface{},
 | 
						|
		fe func(*Encoder, *codecFnInfo, reflect.Value),
 | 
						|
		fd func(*Decoder, *codecFnInfo, reflect.Value)) {
 | 
						|
		xrt := reflect.TypeOf(v)
 | 
						|
		xptr := rt2id(xrt)
 | 
						|
        fastpathAvRtid[i] = xptr
 | 
						|
		fastpathAv[i] = fastpathE{xrt, fe, fd}
 | 
						|
		i++
 | 
						|
	}
 | 
						|
	{{/* do not register []byte in fast-path */}}
 | 
						|
	{{range .Values}}{{if not .Primitive}}{{if not .MapKey -}}
 | 
						|
	fn([]{{ .Elem }}(nil), (*Encoder).{{ .MethodNamePfx "fastpathEnc" false }}R, (*Decoder).{{ .MethodNamePfx "fastpathDec" false }}R)
 | 
						|
	{{end}}{{end}}{{end}}
 | 
						|
	
 | 
						|
	{{range .Values}}{{if not .Primitive}}{{if .MapKey -}}
 | 
						|
	fn(map[{{ .MapKey }}]{{ .Elem }}(nil), (*Encoder).{{ .MethodNamePfx "fastpathEnc" false }}R, (*Decoder).{{ .MethodNamePfx "fastpathDec" false }}R)
 | 
						|
	{{end}}{{end}}{{end}}
 | 
						|
	
 | 
						|
	sort.Sort(fastpathAslice{})
 | 
						|
}
 | 
						|
 | 
						|
// -- encode
 | 
						|
 | 
						|
// -- -- fast path type switch
 | 
						|
func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool {
 | 
						|
	switch v := iv.(type) {
 | 
						|
{{range .Values}}{{if not .Primitive}}{{if not .MapKey -}}
 | 
						|
	case []{{ .Elem }}:
 | 
						|
		fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
 | 
						|
	case *[]{{ .Elem }}:
 | 
						|
		if *v == nil {
 | 
						|
			e.e.EncodeNil()
 | 
						|
		} else {
 | 
						|
			fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, e)
 | 
						|
		}
 | 
						|
{{end}}{{end}}{{end -}}
 | 
						|
 | 
						|
{{range .Values}}{{if not .Primitive}}{{if .MapKey -}}
 | 
						|
	case map[{{ .MapKey }}]{{ .Elem }}:
 | 
						|
		fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
 | 
						|
	case *map[{{ .MapKey }}]{{ .Elem }}:
 | 
						|
		if *v == nil {
 | 
						|
			e.e.EncodeNil()
 | 
						|
		} else {
 | 
						|
			fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, e)
 | 
						|
		}
 | 
						|
{{end}}{{end}}{{end -}}
 | 
						|
 | 
						|
	default:
 | 
						|
		_ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
// -- -- fast path functions
 | 
						|
{{range .Values}}{{if not .Primitive}}{{if not .MapKey -}} 
 | 
						|
func (e *Encoder) {{ .MethodNamePfx "fastpathEnc" false }}R(f *codecFnInfo, rv reflect.Value) {
 | 
						|
	var v  []{{ .Elem }}
 | 
						|
	if rv.Kind() == reflect.Array {
 | 
						|
		rvGetSlice4Array(rv, &v)
 | 
						|
	} else {
 | 
						|
		v = rv2i(rv).([]{{ .Elem }})
 | 
						|
	}
 | 
						|
	if f.ti.mbs {
 | 
						|
		fastpathTV.{{ .MethodNamePfx "EncAsMap" false }}V(v, e)
 | 
						|
	} else {
 | 
						|
		fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
 | 
						|
	}
 | 
						|
}
 | 
						|
func (fastpathT) {{ .MethodNamePfx "Enc" false }}V(v []{{ .Elem }}, e *Encoder) {
 | 
						|
	{{/* if v == nil { e.e.EncodeNil(); return } */ -}}
 | 
						|
	{{ if eq .Elem "uint8" "byte" -}}
 | 
						|
	e.e.EncodeStringBytesRaw(v)
 | 
						|
	{{ else -}}
 | 
						|
	e.arrayStart(len(v))
 | 
						|
	for j := range v {
 | 
						|
		e.arrayElem()
 | 
						|
		{{ encmd .Elem "v[j]"}}
 | 
						|
	} 
 | 
						|
	e.arrayEnd()
 | 
						|
	{{ end -}}
 | 
						|
}
 | 
						|
func (fastpathT) {{ .MethodNamePfx "EncAsMap" false }}V(v []{{ .Elem }}, e *Encoder) {
 | 
						|
	{{/* if v == nil { e.e.EncodeNil() } else */ -}}
 | 
						|
	e.haltOnMbsOddLen(len(v))
 | 
						|
	{{/*
 | 
						|
	if len(v)&1 != 0 { // similar to &1==1 or %2 == 1
 | 
						|
		e.errorf(fastpathMapBySliceErrMsg, len(v))
 | 
						|
	}
 | 
						|
	*/ -}}
 | 
						|
	e.mapStart(len(v) >> 1) // e.mapStart(len(v) / 2)
 | 
						|
	for j := range v {
 | 
						|
		if j&1 == 0 { // if j%2 == 0 {
 | 
						|
			e.mapElemKey()
 | 
						|
		} else {
 | 
						|
			e.mapElemValue()
 | 
						|
		}
 | 
						|
		{{ encmd .Elem "v[j]"}}
 | 
						|
	}
 | 
						|
	e.mapEnd()
 | 
						|
}
 | 
						|
{{end}}{{end}}{{end -}}
 | 
						|
 | 
						|
{{range .Values}}{{if not .Primitive}}{{if .MapKey -}}
 | 
						|
func (e *Encoder) {{ .MethodNamePfx "fastpathEnc" false }}R(f *codecFnInfo, rv reflect.Value) {
 | 
						|
	fastpathTV.{{ .MethodNamePfx "Enc" false }}V(rv2i(rv).(map[{{ .MapKey }}]{{ .Elem }}), e)
 | 
						|
}
 | 
						|
func (fastpathT) {{ .MethodNamePfx "Enc" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, e *Encoder) {
 | 
						|
	{{/* if v == nil { e.e.EncodeNil(); return } */ -}}
 | 
						|
	e.mapStart(len(v))
 | 
						|
	if e.h.Canonical { {{/* need to figure out .NoCanonical */}}
 | 
						|
		{{if eq .MapKey "interface{}"}}{{/* out of band */ -}}
 | 
						|
		var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
 | 
						|
		e2 := NewEncoderBytes(&mksv, e.hh)
 | 
						|
		v2 := make([]bytesIntf, len(v))
 | 
						|
		var i, l uint {{/* put loop variables outside. seems currently needed for better perf */}}
 | 
						|
		var vp *bytesIntf
 | 
						|
		for k2 := range v {
 | 
						|
			l = uint(len(mksv))
 | 
						|
			e2.MustEncode(k2)
 | 
						|
			vp = &v2[i]
 | 
						|
			vp.v = mksv[l:]
 | 
						|
			vp.i = k2 
 | 
						|
			i++
 | 
						|
		}
 | 
						|
		sort.Sort(bytesIntfSlice(v2))
 | 
						|
		for j := range v2 {
 | 
						|
			e.mapElemKey()
 | 
						|
			e.asis(v2[j].v)
 | 
						|
			e.mapElemValue()
 | 
						|
			e.encode(v[v2[j].i])
 | 
						|
		} {{else}}{{ $x := sorttype .MapKey true}}v2 := make([]{{ $x }}, len(v))
 | 
						|
		var i uint
 | 
						|
		for k := range v {
 | 
						|
			v2[i] = {{if eq $x .MapKey}}k{{else}}{{ $x }}(k){{end}}
 | 
						|
			i++
 | 
						|
		}
 | 
						|
		sort.Sort({{ sorttype .MapKey false}}(v2))
 | 
						|
		for _, k2 := range v2 {
 | 
						|
			e.mapElemKey()
 | 
						|
			{{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}}
 | 
						|
			e.mapElemValue()
 | 
						|
			{{ $y := printf "v[%s(k2)]" .MapKey }}{{if eq $x .MapKey }}{{ $y = "v[k2]" }}{{end}}{{ encmd .Elem $y }}
 | 
						|
		} {{end}}
 | 
						|
	} else { 
 | 
						|
		for k2, v2 := range v {
 | 
						|
			e.mapElemKey()
 | 
						|
			{{if eq .MapKey "string"}} e.e.EncodeString(k2) {{else}}{{ encmd .MapKey "k2"}}{{end}}
 | 
						|
			e.mapElemValue()
 | 
						|
			{{ encmd .Elem "v2"}}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	e.mapEnd()
 | 
						|
}
 | 
						|
{{end}}{{end}}{{end -}}
 | 
						|
 | 
						|
// -- decode
 | 
						|
 | 
						|
// -- -- fast path type switch
 | 
						|
func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool {
 | 
						|
	var changed bool
 | 
						|
	var containerLen int
 | 
						|
	switch v := iv.(type) {
 | 
						|
{{range .Values}}{{if not .Primitive}}{{if not .MapKey -}}
 | 
						|
	case []{{ .Elem }}:
 | 
						|
		fastpathTV.{{ .MethodNamePfx "Dec" false }}N(v, d)
 | 
						|
	case *[]{{ .Elem }}:
 | 
						|
		var v2 []{{ .Elem }}
 | 
						|
		if v2, changed = fastpathTV.{{ .MethodNamePfx "Dec" false }}Y(*v, d); changed {
 | 
						|
			*v = v2
 | 
						|
		}
 | 
						|
{{end}}{{end}}{{end -}}
 | 
						|
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}{{/*
 | 
						|
// maps only change if nil, and in that case, there's no point copying
 | 
						|
*/ -}}
 | 
						|
	case map[{{ .MapKey }}]{{ .Elem }}:
 | 
						|
		containerLen = d.mapStart(d.d.ReadMapStart())
 | 
						|
		if containerLen != containerLenNil {
 | 
						|
			if containerLen != 0 {
 | 
						|
				fastpathTV.{{ .MethodNamePfx "Dec" false }}L(v, containerLen, d)
 | 
						|
			}
 | 
						|
			d.mapEnd()
 | 
						|
		}
 | 
						|
	case *map[{{ .MapKey }}]{{ .Elem }}:
 | 
						|
		{{/*
 | 
						|
		containerLen = d.mapStart(d.d.ReadMapStart())
 | 
						|
		if containerLen == 0 {
 | 
						|
			d.mapEnd()
 | 
						|
		} else if containerLen == containerLenNil {
 | 
						|
			*v = nil
 | 
						|
		} else {
 | 
						|
			if *v == nil {
 | 
						|
				*v = make(map[{{ .MapKey }}]{{ .Elem }}, decInferLen(containerLen, d.h.MaxInitLen, {{ .Size }}))
 | 
						|
			}
 | 
						|
			fastpathTV.{{ .MethodNamePfx "Dec" false }}L(*v, containerLen, d)
 | 
						|
		}
 | 
						|
		// consider delegating fully to X - encoding *map is uncommon, so ok to pay small function call cost
 | 
						|
		*/ -}}
 | 
						|
		fastpathTV.{{ .MethodNamePfx "Dec" false }}X(v, d)
 | 
						|
{{end}}{{end}}{{end -}}
 | 
						|
	default:
 | 
						|
		_ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
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
 | 
						|
}
 | 
						|
 | 
						|
// -- -- fast path functions
 | 
						|
{{range .Values}}{{if not .Primitive}}{{if not .MapKey -}}
 | 
						|
{{/*
 | 
						|
Slices can change if they
 | 
						|
- did not come from an array
 | 
						|
- are addressable (from a ptr)
 | 
						|
- are settable (e.g. contained in an interface{})
 | 
						|
*/}}
 | 
						|
func (d *Decoder) {{ .MethodNamePfx "fastpathDec" false }}R(f *codecFnInfo, rv reflect.Value) {
 | 
						|
	{{/*
 | 
						|
    // seqTypeArray=true means that we are not getting a pointer, so no need to check that.
 | 
						|
    if f.seq != seqTypeArray && rv.Kind() == reflect.Ptr {
 | 
						|
    */ -}}
 | 
						|
	var v  []{{ .Elem }}
 | 
						|
	switch rv.Kind() {
 | 
						|
	case reflect.Ptr:
 | 
						|
		vp := rv2i(rv).(*[]{{ .Elem }})
 | 
						|
		var changed bool
 | 
						|
		if v, changed = fastpathTV.{{ .MethodNamePfx "Dec" false }}Y(*vp, d); changed {
 | 
						|
			*vp = v
 | 
						|
		}
 | 
						|
	case reflect.Array:
 | 
						|
		rvGetSlice4Array(rv, &v)
 | 
						|
		fastpathTV.{{ .MethodNamePfx "Dec" false }}N(v, d)
 | 
						|
	default:
 | 
						|
		fastpathTV.{{ .MethodNamePfx "Dec" false }}N(rv2i(rv).([]{{ .Elem }}), d)
 | 
						|
	}
 | 
						|
}
 | 
						|
func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *[]{{ .Elem }}, d *Decoder) {
 | 
						|
	if v, changed := f.{{ .MethodNamePfx "Dec" false }}Y(*vp, d); changed { *vp = v }
 | 
						|
}
 | 
						|
func (fastpathT) {{ .MethodNamePfx "Dec" false }}Y(v []{{ .Elem }}, d *Decoder) (v2 []{{ .Elem }}, changed bool) {
 | 
						|
	{{ if eq .Elem "uint8" "byte" -}}
 | 
						|
	switch d.d.ContainerType() {
 | 
						|
	case valueTypeNil, valueTypeMap:
 | 
						|
		break
 | 
						|
	default:
 | 
						|
		v2 = d.decodeBytesInto(v[:len(v):len(v)])
 | 
						|
		changed = !(len(v2) > 0 && len(v2) == len(v) && &v2[0] == &v[0]) // not same slice
 | 
						|
		return
 | 
						|
	}
 | 
						|
	{{ end -}}
 | 
						|
	slh, containerLenS := d.decSliceHelperStart()
 | 
						|
	if slh.IsNil {
 | 
						|
		if v == nil { return }
 | 
						|
		return nil, true
 | 
						|
	}
 | 
						|
	if containerLenS == 0 {
 | 
						|
		if v == nil { v = []{{ .Elem }}{} } else if len(v) != 0 { v = v[:0] }
 | 
						|
		slh.End()
 | 
						|
		return v, true
 | 
						|
	}
 | 
						|
	hasLen := containerLenS > 0
 | 
						|
	var xlen int 
 | 
						|
	if hasLen {
 | 
						|
		if containerLenS > cap(v) {
 | 
						|
			xlen = decInferLen(containerLenS, d.h.MaxInitLen, {{ .Size }})
 | 
						|
			if xlen <= cap(v) {
 | 
						|
				v = v[:uint(xlen)]
 | 
						|
			} else {
 | 
						|
				v = make([]{{ .Elem }}, uint(xlen))
 | 
						|
			}
 | 
						|
			changed = true 
 | 
						|
		} else if containerLenS != len(v) {
 | 
						|
			v = v[:containerLenS]
 | 
						|
			changed = true
 | 
						|
		}
 | 
						|
	}
 | 
						|
	var j int
 | 
						|
	for j = 0; (hasLen && j < containerLenS) || !(hasLen || d.checkBreak()); j++ {
 | 
						|
		if j == 0 && len(v) == 0 { // means hasLen == false
 | 
						|
			xlen = decInferLen(containerLenS, d.h.MaxInitLen, {{ .Size }}) {{/* xlen = decDefSliceCap */}}
 | 
						|
			v = make([]{{ .Elem }}, uint(xlen))
 | 
						|
			changed = true
 | 
						|
		}
 | 
						|
		{{/* // if indefinite, etc, then expand the slice if necessary */ -}}
 | 
						|
		if j >= len(v) {
 | 
						|
			v = append(v, {{ zerocmd .Elem }})
 | 
						|
			changed = true
 | 
						|
		} 
 | 
						|
		slh.ElemContainerState(j)
 | 
						|
		{{ if eq .Elem "interface{}" }}d.decode(&v[uint(j)]){{ else }}v[uint(j)] = {{ decmd .Elem false }}{{ end }}
 | 
						|
	}
 | 
						|
	if j < len(v) {
 | 
						|
		v = v[:uint(j)]
 | 
						|
		changed = true
 | 
						|
	} else if j == 0 && v == nil {
 | 
						|
		v = []{{ .Elem }}{}
 | 
						|
		changed = true
 | 
						|
	}
 | 
						|
	slh.End()
 | 
						|
	return v, changed
 | 
						|
}
 | 
						|
func (fastpathT) {{ .MethodNamePfx "Dec" false }}N(v []{{ .Elem }}, d *Decoder) {
 | 
						|
	{{ if eq .Elem "uint8" "byte" -}}
 | 
						|
	switch d.d.ContainerType() {
 | 
						|
	case valueTypeNil, valueTypeMap:
 | 
						|
		break
 | 
						|
	default:
 | 
						|
		v2 := d.decodeBytesInto(v[:len(v):len(v)])
 | 
						|
		if !(len(v2) > 0 && len(v2) == len(v) && &v2[0] == &v[0]) { // not same slice
 | 
						|
			copy(v, v2)
 | 
						|
		}
 | 
						|
		return
 | 
						|
	}
 | 
						|
	{{ end -}}
 | 
						|
	slh, containerLenS := d.decSliceHelperStart()
 | 
						|
	if slh.IsNil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if containerLenS == 0 {
 | 
						|
		slh.End()
 | 
						|
		return
 | 
						|
	}
 | 
						|
	hasLen := containerLenS > 0
 | 
						|
	for j := 0; (hasLen && j < containerLenS) || !(hasLen || d.checkBreak()); j++ {
 | 
						|
		{{/* // if indefinite, etc, then expand the slice if necessary */ -}}
 | 
						|
		if j >= len(v) {
 | 
						|
			slh.arrayCannotExpand(hasLen, len(v), j, containerLenS)
 | 
						|
			return
 | 
						|
		} 
 | 
						|
		slh.ElemContainerState(j)
 | 
						|
		{{ if eq .Elem "interface{}" -}}
 | 
						|
		d.decode(&v[uint(j)])
 | 
						|
		{{- else -}}
 | 
						|
		v[uint(j)] = {{ decmd .Elem false }}
 | 
						|
		{{- end }}
 | 
						|
	}
 | 
						|
	slh.End()
 | 
						|
}
 | 
						|
{{end}}{{end}}{{end -}}
 | 
						|
 | 
						|
{{range .Values}}{{if not .Primitive}}{{if .MapKey -}}
 | 
						|
{{/*
 | 
						|
Maps can change if they are
 | 
						|
- addressable (from a ptr)
 | 
						|
- settable (e.g. contained in an interface{})
 | 
						|
 | 
						|
Also, these methods are called by decodeValue directly, after handling a TryNil.
 | 
						|
Consequently, there's no need to check for containerLenNil here.
 | 
						|
*/ -}}
 | 
						|
func (d *Decoder) {{ .MethodNamePfx "fastpathDec" false }}R(f *codecFnInfo, rv reflect.Value) {
 | 
						|
	containerLen := d.mapStart(d.d.ReadMapStart())
 | 
						|
    {{/*
 | 
						|
	if containerLen == containerLenNil {
 | 
						|
		if rv.Kind() == reflect.Ptr {
 | 
						|
			*(rv2i(rv).(*map[{{ .MapKey }}]{{ .Elem }})) = nil
 | 
						|
		}
 | 
						|
        return
 | 
						|
	}
 | 
						|
    */ -}}
 | 
						|
	if rv.Kind() == reflect.Ptr {
 | 
						|
		vp, _ := rv2i(rv).(*map[{{ .MapKey }}]{{ .Elem }})
 | 
						|
		if *vp == nil {
 | 
						|
			*vp = make(map[{{ .MapKey }}]{{ .Elem }}, decInferLen(containerLen, d.h.MaxInitLen, {{ .Size }}))
 | 
						|
		}
 | 
						|
		if containerLen != 0 {
 | 
						|
			fastpathTV.{{ .MethodNamePfx "Dec" false }}L(*vp, containerLen, d)
 | 
						|
		}
 | 
						|
	} else if containerLen != 0 {
 | 
						|
		fastpathTV.{{ .MethodNamePfx "Dec" false }}L(rv2i(rv).(map[{{ .MapKey }}]{{ .Elem }}), containerLen, d)
 | 
						|
	}
 | 
						|
	d.mapEnd()
 | 
						|
}
 | 
						|
func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *map[{{ .MapKey }}]{{ .Elem }}, d *Decoder) {
 | 
						|
	containerLen := d.mapStart(d.d.ReadMapStart())
 | 
						|
	if containerLen == containerLenNil {
 | 
						|
		*vp = nil
 | 
						|
	} else {
 | 
						|
		if *vp == nil {
 | 
						|
			*vp = make(map[{{ .MapKey }}]{{ .Elem }}, decInferLen(containerLen, d.h.MaxInitLen, {{ .Size }}))
 | 
						|
		}
 | 
						|
		if containerLen != 0 {
 | 
						|
			f.{{ .MethodNamePfx "Dec" false }}L(*vp, containerLen, d)
 | 
						|
		}
 | 
						|
		d.mapEnd()
 | 
						|
	}
 | 
						|
}
 | 
						|
func (fastpathT) {{ .MethodNamePfx "Dec" false }}L(v map[{{ .MapKey }}]{{ .Elem }}, containerLen int, d *Decoder) {
 | 
						|
	{{/* No need to check if containerLen == containerLenNil, as that is checked by R and L above  */ -}}
 | 
						|
	if v == nil {
 | 
						|
		d.errorf("cannot decode into nil map[{{ .MapKey }}]{{ .Elem }} given stream length: %v", containerLen)
 | 
						|
        {{/* d.swallowMapContents(containerLen) */ -}}
 | 
						|
		return
 | 
						|
	}
 | 
						|
	{{if eq .Elem "interface{}" }}mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
 | 
						|
    {{else if eq .Elem "bytes" "[]byte" }}mapGet := v != nil && !d.h.MapValueReset
 | 
						|
    {{end -}}
 | 
						|
    var mk {{ .MapKey }}
 | 
						|
	var mv {{ .Elem }}
 | 
						|
	hasLen := containerLen > 0
 | 
						|
	for j := 0; (hasLen && j < containerLen) || !(hasLen || d.checkBreak()); j++ {
 | 
						|
		d.mapElemKey()
 | 
						|
		{{ if eq .MapKey "interface{}" }}mk = nil 
 | 
						|
		d.decode(&mk)
 | 
						|
		if bv, bok := mk.([]byte); bok {
 | 
						|
			mk = d.stringZC(bv) {{/* // maps cannot have []byte as key. switch to string. */}}
 | 
						|
		}{{ else }}mk = {{ decmd .MapKey true }}{{ end }}
 | 
						|
		d.mapElemValue()
 | 
						|
		{{ if eq .Elem "interface{}" "[]byte" "bytes" -}}
 | 
						|
		if mapGet { mv = v[mk] } else { mv = nil }
 | 
						|
		{{ end -}}
 | 
						|
		{{ if eq .Elem "interface{}" -}}
 | 
						|
		d.decode(&mv)
 | 
						|
		{{ else if eq .Elem "[]byte" "bytes" -}}
 | 
						|
		mv = d.decodeBytesInto(mv)
 | 
						|
		{{ else -}}
 | 
						|
		mv = {{ decmd .Elem false }}
 | 
						|
		{{ end -}}
 | 
						|
		v[mk] = mv
 | 
						|
	}
 | 
						|
}
 | 
						|
{{end}}{{end}}{{end}}
 |