...

Text file src/github.com/ugorji/go/codec/fast-path.go.tmpl

Documentation: github.com/ugorji/go/codec

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

View as plain text