summaryrefslogtreecommitdiff
path: root/vendor/github.com/ugorji/go/codec/decode.base.go
diff options
context:
space:
mode:
authorLibravatar kim <grufwub@gmail.com>2025-06-30 15:19:09 +0200
committerLibravatar kim <gruf@noreply.codeberg.org>2025-06-30 15:19:09 +0200
commit8b0ea560279a5bf4479555d3924c763ddeecfcad (patch)
tree005e26d4a658e565594fb259cc17948659195822 /vendor/github.com/ugorji/go/codec/decode.base.go
parent[chore] bumps ncruces/go-sqlite3 v0.26.1 => v0.26.3 (#4302) (diff)
downloadgotosocial-8b0ea560279a5bf4479555d3924c763ddeecfcad.tar.xz
[chore] update go dependencies (#4304)
- github.com/KimMachineGun/automemlimit v0.7.2 => v0.7.3 - github.com/gin-contrib/cors v1.7.5 => v1.7.6 - github.com/minio/minio-go/v7 v7.0.92 => v7.0.94 - github.com/spf13/cast v1.8.0 => v1.9.2 - github.com/uptrace/bun{,/*} v1.2.11 => v1.2.14 - golang.org/x/image v0.27.0 => v0.28.0 - golang.org/x/net v0.40.0 => v0.41.0 - code.superseriousbusiness.org/go-swagger v0.31.0-gts-go1.23-fix => v0.32.3-gts-go1.23-fix Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4304 Co-authored-by: kim <grufwub@gmail.com> Co-committed-by: kim <grufwub@gmail.com>
Diffstat (limited to 'vendor/github.com/ugorji/go/codec/decode.base.go')
-rw-r--r--vendor/github.com/ugorji/go/codec/decode.base.go944
1 files changed, 944 insertions, 0 deletions
diff --git a/vendor/github.com/ugorji/go/codec/decode.base.go b/vendor/github.com/ugorji/go/codec/decode.base.go
new file mode 100644
index 000000000..e82f40252
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/decode.base.go
@@ -0,0 +1,944 @@
+// 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.
+
+package codec
+
+import (
+ "errors"
+ "io"
+ "math"
+ "reflect"
+ "slices"
+ "sync"
+ "time"
+)
+
+func init() {
+ for _, v := range []interface{}{
+ (*string)(nil),
+ (*bool)(nil),
+ (*int)(nil),
+ (*int8)(nil),
+ (*int16)(nil),
+ (*int32)(nil),
+ (*int64)(nil),
+ (*uint)(nil),
+ (*uint8)(nil),
+ (*uint16)(nil),
+ (*uint32)(nil),
+ (*uint64)(nil),
+ (*uintptr)(nil),
+ (*float32)(nil),
+ (*float64)(nil),
+ (*complex64)(nil),
+ (*complex128)(nil),
+ (*[]byte)(nil),
+ ([]byte)(nil),
+ (*time.Time)(nil),
+ (*Raw)(nil),
+ (*interface{})(nil),
+ } {
+ decBuiltinRtids = append(decBuiltinRtids, i2rtid(v))
+ }
+ slices.Sort(decBuiltinRtids)
+}
+
+const msgBadDesc = "unrecognized descriptor byte"
+
+var decBuiltinRtids []uintptr
+
+// decDriver calls (DecodeBytes and DecodeStringAsBytes) return a state
+// of the view they return, allowing consumers to handle appropriately.
+//
+// sequencing of this is intentional:
+// - mutable if <= dBytesAttachBuffer (buf | view | invalid)
+// - noCopy if >= dBytesAttachViewZerocopy
+type dBytesAttachState uint8
+
+const (
+ dBytesAttachInvalid dBytesAttachState = iota
+ dBytesAttachView // (bytes && !zerocopy && !buf)
+ dBytesAttachBuffer // (buf)
+ dBytesAttachViewZerocopy // (bytes && zerocopy && !buf)
+ dBytesDetach // (!bytes && !buf)
+)
+
+type dBytesIntoState uint8
+
+const (
+ dBytesIntoNoChange dBytesIntoState = iota
+ dBytesIntoParamOut
+ dBytesIntoParamOutSlice
+ dBytesIntoNew
+)
+
+func (x dBytesAttachState) String() string {
+ switch x {
+ case dBytesAttachInvalid:
+ return "invalid"
+ case dBytesAttachView:
+ return "view"
+ case dBytesAttachBuffer:
+ return "buffer"
+ case dBytesAttachViewZerocopy:
+ return "view-zerocopy"
+ case dBytesDetach:
+ return "detach"
+ }
+ return "unknown"
+}
+
+const (
+ decDefMaxDepth = 1024 // maximum depth
+ decDefChanCap = 64 // should be large, as cap cannot be expanded
+ decScratchByteArrayLen = (4 + 3) * 8 // around cacheLineSize ie ~64, depending on Decoder size
+
+ // MARKER: massage decScratchByteArrayLen to ensure xxxDecDriver structs fit within cacheLine*N
+
+ // decFailNonEmptyIntf configures whether we error
+ // when decoding naked into a non-empty interface.
+ //
+ // Typically, we cannot decode non-nil stream value into
+ // nil interface with methods (e.g. io.Reader).
+ // However, in some scenarios, this should be allowed:
+ // - MapType
+ // - SliceType
+ // - Extensions
+ //
+ // Consequently, we should relax this. Put it behind a const flag for now.
+ decFailNonEmptyIntf = false
+
+ // decUseTransient says whether we should use the transient optimization.
+ //
+ // There's potential for GC corruption or memory overwrites if transient isn't
+ // used carefully, so this flag helps turn it off quickly if needed.
+ //
+ // Use it everywhere needed so we can completely remove unused code blocks.
+ decUseTransient = true
+)
+
+var (
+ errNeedMapOrArrayDecodeToStruct = errors.New("only encoded map or array can decode into struct")
+ errCannotDecodeIntoNil = errors.New("cannot decode into nil")
+
+ errExpandSliceCannotChange = errors.New("expand slice: cannot change")
+
+ errDecoderNotInitialized = errors.New("Decoder not initialized")
+
+ errDecUnreadByteNothingToRead = errors.New("cannot unread - nothing has been read")
+ errDecUnreadByteLastByteNotRead = errors.New("cannot unread - last byte has not been read")
+ errDecUnreadByteUnknown = errors.New("cannot unread - reason unknown")
+ errMaxDepthExceeded = errors.New("maximum decoding depth exceeded")
+)
+
+type decNotDecodeableReason uint8
+
+const (
+ decNotDecodeableReasonUnknown decNotDecodeableReason = iota
+ decNotDecodeableReasonBadKind
+ decNotDecodeableReasonNonAddrValue
+ decNotDecodeableReasonNilReference
+)
+
+type decDriverI interface {
+
+ // this will check if the next token is a break.
+ CheckBreak() bool
+
+ // TryNil tries to decode as nil.
+ // If a nil is in the stream, it consumes it and returns true.
+ //
+ // Note: if TryNil returns true, that must be handled.
+ TryNil() bool
+
+ // ContainerType returns one of: Bytes, String, Nil, Slice or Map.
+ //
+ // Return unSet if not known.
+ //
+ // Note: Implementations MUST fully consume sentinel container types, specifically Nil.
+ ContainerType() (vt valueType)
+
+ // DecodeNaked will decode primitives (number, bool, string, []byte) and RawExt.
+ // For maps and arrays, it will not do the decoding in-band, but will signal
+ // the decoder, so that is done later, by setting the fauxUnion.valueType field.
+ //
+ // Note: Numbers are decoded as int64, uint64, float64 only (no smaller sized number types).
+ // for extensions, DecodeNaked must read the tag and the []byte if it exists.
+ // if the []byte is not read, then kInterfaceNaked will treat it as a Handle
+ // that stores the subsequent value in-band, and complete reading the RawExt.
+ //
+ // extensions should also use readx to decode them, for efficiency.
+ // kInterface will extract the detached byte slice if it has to pass it outside its realm.
+ DecodeNaked()
+
+ DecodeInt64() (i int64)
+ DecodeUint64() (ui uint64)
+
+ DecodeFloat32() (f float32)
+ DecodeFloat64() (f float64)
+
+ DecodeBool() (b bool)
+
+ // DecodeStringAsBytes returns the bytes representing a string.
+ // It will return a view into scratch buffer or input []byte (if applicable).
+ //
+ // Note: This can also decode symbols, if supported.
+ //
+ // Users should consume it right away and not store it for later use.
+ DecodeStringAsBytes() (v []byte, state dBytesAttachState)
+
+ // DecodeBytes returns the bytes representing a binary value.
+ // It will return a view into scratch buffer or input []byte (if applicable).
+ DecodeBytes() (out []byte, state dBytesAttachState)
+ // DecodeBytes(bs []byte, isstring, zerocopy bool) (bsOut []byte)
+
+ // DecodeExt will decode into an extension.
+ // ext is never nil.
+ DecodeExt(v interface{}, basetype reflect.Type, xtag uint64, ext Ext)
+ // decodeExt(verifyTag bool, tag byte) (xtag byte, xbs []byte)
+
+ // DecodeRawExt will decode into a *RawExt
+ DecodeRawExt(re *RawExt)
+
+ DecodeTime() (t time.Time)
+
+ // ReadArrayStart will return the length of the array.
+ // If the format doesn't prefix the length, it returns containerLenUnknown.
+ // If the expected array was a nil in the stream, it returns containerLenNil.
+ ReadArrayStart() int
+
+ // ReadMapStart will return the length of the array.
+ // If the format doesn't prefix the length, it returns containerLenUnknown.
+ // If the expected array was a nil in the stream, it returns containerLenNil.
+ ReadMapStart() int
+
+ decDriverContainerTracker
+
+ reset()
+
+ // atEndOfDecode()
+
+ // nextValueBytes will return the bytes representing the next value in the stream.
+ // It generally will include the last byte read, as that is a part of the next value
+ // in the stream.
+ nextValueBytes() []byte
+
+ // descBd will describe the token descriptor that signifies what type was decoded
+ descBd() string
+
+ // isBytes() bool
+
+ resetInBytes(in []byte)
+ resetInIO(r io.Reader)
+
+ NumBytesRead() int
+
+ init(h Handle, shared *decoderBase, dec decoderI) (fp interface{})
+
+ // driverStateManager
+ decNegintPosintFloatNumber
+}
+
+type decInit2er struct{}
+
+func (decInit2er) init2(dec decoderI) {}
+
+type decDriverContainerTracker interface {
+ ReadArrayElem(firstTime bool)
+ ReadMapElemKey(firstTime bool)
+ ReadMapElemValue()
+ ReadArrayEnd()
+ ReadMapEnd()
+}
+
+type decNegintPosintFloatNumber interface {
+ decInteger() (ui uint64, neg, ok bool)
+ decFloat() (f float64, ok bool)
+}
+
+type decDriverNoopNumberHelper struct{}
+
+func (x decDriverNoopNumberHelper) decInteger() (ui uint64, neg, ok bool) {
+ panic("decInteger unsupported")
+}
+func (x decDriverNoopNumberHelper) decFloat() (f float64, ok bool) { panic("decFloat unsupported") }
+
+type decDriverNoopContainerReader struct{}
+
+func (x decDriverNoopContainerReader) ReadArrayStart() (v int) { panic("ReadArrayStart unsupported") }
+func (x decDriverNoopContainerReader) ReadMapStart() (v int) { panic("ReadMapStart unsupported") }
+func (x decDriverNoopContainerReader) ReadArrayEnd() {}
+func (x decDriverNoopContainerReader) ReadMapEnd() {}
+func (x decDriverNoopContainerReader) ReadArrayElem(firstTime bool) {}
+func (x decDriverNoopContainerReader) ReadMapElemKey(firstTime bool) {}
+func (x decDriverNoopContainerReader) ReadMapElemValue() {}
+func (x decDriverNoopContainerReader) CheckBreak() (v bool) { return }
+
+// ----
+
+type decFnInfo struct {
+ ti *typeInfo
+ xfFn Ext
+ xfTag uint64
+ addrD bool // decoding into a pointer is preferred
+ addrDf bool // force: if addrD, then decode function MUST take a ptr
+}
+
+// DecodeOptions captures configuration options during decode.
+type DecodeOptions struct {
+ // MapType specifies type to use during schema-less decoding of a map in the stream.
+ // If nil (unset), we default to map[string]interface{} iff json handle and MapKeyAsString=true,
+ // else map[interface{}]interface{}.
+ MapType reflect.Type
+
+ // SliceType specifies type to use during schema-less decoding of an array in the stream.
+ // If nil (unset), we default to []interface{} for all formats.
+ SliceType reflect.Type
+
+ // MaxInitLen defines the maxinum initial length that we "make" a collection
+ // (string, slice, map, chan). If 0 or negative, we default to a sensible value
+ // based on the size of an element in the collection.
+ //
+ // For example, when decoding, a stream may say that it has 2^64 elements.
+ // We should not auto-matically provision a slice of that size, to prevent Out-Of-Memory crash.
+ // Instead, we provision up to MaxInitLen, fill that up, and start appending after that.
+ MaxInitLen int
+
+ // ReaderBufferSize is the size of the buffer used when reading.
+ //
+ // if > 0, we use a smart buffer internally for performance purposes.
+ ReaderBufferSize int
+
+ // MaxDepth defines the maximum depth when decoding nested
+ // maps and slices. If 0 or negative, we default to a suitably large number (currently 1024).
+ MaxDepth int16
+
+ // If ErrorIfNoField, return an error when decoding a map
+ // from a codec stream into a struct, and no matching struct field is found.
+ ErrorIfNoField bool
+
+ // If ErrorIfNoArrayExpand, return an error when decoding a slice/array that cannot be expanded.
+ // For example, the stream contains an array of 8 items, but you are decoding into a [4]T array,
+ // or you are decoding into a slice of length 4 which is non-addressable (and so cannot be set).
+ ErrorIfNoArrayExpand bool
+
+ // If SignedInteger, use the int64 during schema-less decoding of unsigned values (not uint64).
+ SignedInteger bool
+
+ // MapValueReset controls how we decode into a map value.
+ //
+ // By default, we MAY retrieve the mapping for a key, and then decode into that.
+ // However, especially with big maps, that retrieval may be expensive and unnecessary
+ // if the stream already contains all that is necessary to recreate the value.
+ //
+ // If true, we will never retrieve the previous mapping,
+ // but rather decode into a new value and set that in the map.
+ //
+ // If false, we will retrieve the previous mapping if necessary e.g.
+ // the previous mapping is a pointer, or is a struct or array with pre-set state,
+ // or is an interface.
+ MapValueReset bool
+
+ // SliceElementReset: on decoding a slice, reset the element to a zero value first.
+ //
+ // concern: if the slice already contained some garbage, we will decode into that garbage.
+ SliceElementReset bool
+
+ // InterfaceReset controls how we decode into an interface.
+ //
+ // By default, when we see a field that is an interface{...},
+ // or a map with interface{...} value, we will attempt decoding into the
+ // "contained" value.
+ //
+ // However, this prevents us from reading a string into an interface{}
+ // that formerly contained a number.
+ //
+ // If true, we will decode into a new "blank" value, and set that in the interface.
+ // If false, we will decode into whatever is contained in the interface.
+ InterfaceReset bool
+
+ // InternString controls interning of strings during decoding.
+ //
+ // Some handles, e.g. json, typically will read map keys as strings.
+ // If the set of keys are finite, it may help reduce allocation to
+ // look them up from a map (than to allocate them afresh).
+ //
+ // Note: Handles will be smart when using the intern functionality.
+ // Every string should not be interned.
+ // An excellent use-case for interning is struct field names,
+ // or map keys where key type is string.
+ InternString bool
+
+ // PreferArrayOverSlice controls whether to decode to an array or a slice.
+ //
+ // This only impacts decoding into a nil interface{}.
+ //
+ // Consequently, it has no effect on codecgen.
+ //
+ // *Note*: This only applies if using go1.5 and above,
+ // as it requires reflect.ArrayOf support which was absent before go1.5.
+ PreferArrayOverSlice bool
+
+ // DeleteOnNilMapValue controls how to decode a nil value in the stream.
+ //
+ // If true, we will delete the mapping of the key.
+ // Else, just set the mapping to the zero value of the type.
+ //
+ // Deprecated: This does NOTHING and is left behind for compiling compatibility.
+ // This change is necessitated because 'nil' in a stream now consistently
+ // means the zero value (ie reset the value to its zero state).
+ DeleteOnNilMapValue bool
+
+ // RawToString controls how raw bytes in a stream are decoded into a nil interface{}.
+ // By default, they are decoded as []byte, but can be decoded as string (if configured).
+ RawToString bool
+
+ // ZeroCopy controls whether decoded values of []byte or string type
+ // point into the input []byte parameter passed to a NewDecoderBytes/ResetBytes(...) call.
+ //
+ // To illustrate, if ZeroCopy and decoding from a []byte (not io.Writer),
+ // then a []byte or string in the output result may just be a slice of (point into)
+ // the input bytes.
+ //
+ // This optimization prevents unnecessary copying.
+ //
+ // However, it is made optional, as the caller MUST ensure that the input parameter []byte is
+ // not modified after the Decode() happens, as any changes are mirrored in the decoded result.
+ ZeroCopy bool
+
+ // PreferPointerForStructOrArray controls whether a struct or array
+ // is stored in a nil interface{}, or a pointer to it.
+ //
+ // This mostly impacts when we decode registered extensions.
+ PreferPointerForStructOrArray bool
+
+ // ValidateUnicode controls will cause decoding to fail if an expected unicode
+ // string is well-formed but include invalid codepoints.
+ //
+ // This could have a performance impact.
+ ValidateUnicode bool
+}
+
+// ----------------------------------------
+
+type decoderBase struct {
+ perType decPerType
+
+ h *BasicHandle
+
+ rtidFn, rtidFnNoExt *atomicRtidFnSlice
+
+ buf []byte
+
+ // used for interning strings
+ is internerMap
+
+ err error
+
+ // sd decoderI
+
+ blist bytesFreeList
+
+ mtr bool // is maptype a known type?
+ str bool // is slicetype a known type?
+ jsms bool // is json handle, and MapKeyAsString
+
+ bytes bool // uses a bytes reader
+ bufio bool // uses a ioDecReader with buffer size > 0
+
+ // ---- cpu cache line boundary?
+ // ---- writable fields during execution --- *try* to keep in sep cache line
+ maxdepth int16
+ depth int16
+
+ // Extensions can call Decode() within a current Decode() call.
+ // We need to know when the top level Decode() call returns,
+ // so we can decide whether to Release() or not.
+ calls uint16 // what depth in mustDecode are we in now.
+
+ c containerState
+
+ // decByteState
+
+ n fauxUnion
+
+ // b is an always-available scratch buffer used by Decoder and decDrivers.
+ // By being always-available, it can be used for one-off things without
+ // having to get from freelist, use, and return back to freelist.
+ //
+ // Use it for a narrow set of things e.g.
+ // - binc uses it for parsing numbers, represented at 8 or less bytes
+ // - uses as potential buffer for struct field names
+ b [decScratchByteArrayLen]byte
+
+ hh Handle
+ // cache the mapTypeId and sliceTypeId for faster comparisons
+ mtid uintptr
+ stid uintptr
+}
+
+func (d *decoderBase) maxInitLen() uint {
+ return uint(max(1024, d.h.MaxInitLen))
+}
+
+func (d *decoderBase) naked() *fauxUnion {
+ return &d.n
+}
+
+func (d *decoderBase) fauxUnionReadRawBytes(dr decDriverI, asString, rawToString bool) { //, handleZeroCopy bool) {
+ // fauxUnion is only used within DecodeNaked calls; consequently, we should try to intern.
+ d.n.l, d.n.a = dr.DecodeBytes()
+ if asString || rawToString {
+ d.n.v = valueTypeString
+ d.n.s = d.detach2Str(d.n.l, d.n.a)
+ } else {
+ d.n.v = valueTypeBytes
+ d.n.l = d.detach2Bytes(d.n.l, d.n.a)
+ }
+}
+
+// Return a fixed (detached) string representation of a []byte.
+//
+// Possibly get an interned version of a string,
+// iff InternString=true and decoding a map key.
+//
+// This should mostly be used for map keys, struct field names, etc
+// where the key type is string. This is because keys of a map/struct are
+// typically reused across many objects.
+func (d *decoderBase) detach2Str(v []byte, state dBytesAttachState) (s string) {
+ // note: string([]byte) checks - and optimizes - for len 0 and len 1
+ if len(v) <= 1 {
+ s = string(v)
+ } else if state >= dBytesAttachViewZerocopy { // !scratchBuf && d.bytes && d.h.ZeroCopy
+ s = stringView(v)
+ } else if d.is == nil || d.c != containerMapKey || len(v) > internMaxStrLen {
+ s = string(v)
+ } else {
+ s = d.is.string(v)
+ }
+ return
+}
+
+func (d *decoderBase) usableStructFieldNameBytes(buf, v []byte, state dBytesAttachState) (out []byte) {
+ // In JSON, mapElemValue reads a colon and spaces.
+ // In bufio mode of ioDecReader, fillbuf could overwrite the read buffer
+ // which readXXX() calls return sub-slices from.
+ //
+ // Consequently, we detach the bytes in this special case.
+ //
+ // Note: ioDecReader (non-bufio) and bytesDecReader do not have
+ // this issue (as no fillbuf exists where bytes might be returned from).
+ if d.bufio && d.h.jsonHandle && state < dBytesAttachViewZerocopy {
+ if cap(buf) > len(v) {
+ out = buf[:len(v)]
+ } else if len(d.b) > len(v) {
+ out = d.b[:len(v)]
+ } else {
+ out = make([]byte, len(v), max(64, len(v)))
+ }
+ copy(out, v)
+ return
+ }
+ return v
+}
+
+func (d *decoderBase) detach2Bytes(in []byte, state dBytesAttachState) (out []byte) {
+ if cap(in) == 0 || state >= dBytesAttachViewZerocopy {
+ return in
+ }
+ if len(in) == 0 {
+ return zeroByteSlice
+ }
+ out = make([]byte, len(in))
+ copy(out, in)
+ return out
+}
+
+func (d *decoderBase) attachState(usingBufFromReader bool) (r dBytesAttachState) {
+ if usingBufFromReader {
+ r = dBytesAttachBuffer
+ } else if !d.bytes {
+ r = dBytesDetach
+ } else if d.h.ZeroCopy {
+ r = dBytesAttachViewZerocopy
+ } else {
+ r = dBytesAttachView
+ }
+ return
+}
+
+func (d *decoderBase) mapStart(v int) int {
+ if v != containerLenNil {
+ d.depthIncr()
+ d.c = containerMapStart
+ }
+ return v
+}
+
+func (d *decoderBase) HandleName() string {
+ return d.hh.Name()
+}
+
+func (d *decoderBase) isBytes() bool {
+ return d.bytes
+}
+
+type decoderI interface {
+ Decode(v interface{}) (err error)
+ HandleName() string
+ MustDecode(v interface{})
+ NumBytesRead() int
+ Release() // deprecated
+ Reset(r io.Reader)
+ ResetBytes(in []byte)
+ ResetString(s string)
+
+ isBytes() bool
+ wrapErr(v error, err *error)
+ swallow()
+
+ nextValueBytes() []byte // wrapper method, for use in tests
+ // getDecDriver() decDriverI
+
+ decode(v interface{})
+ decodeAs(v interface{}, t reflect.Type, ext bool)
+
+ interfaceExtConvertAndDecode(v interface{}, ext InterfaceExt)
+}
+
+var errDecNoResetBytesWithReader = errors.New("cannot reset an Decoder reading from []byte with a io.Reader")
+var errDecNoResetReaderWithBytes = errors.New("cannot reset an Decoder reading from io.Reader with a []byte")
+
+func setZero(iv interface{}) {
+ rv, isnil := isNil(iv, false)
+ if isnil {
+ return
+ }
+ if !rv.IsValid() {
+ rv = reflect.ValueOf(iv)
+ }
+ if isnilBitset.isset(byte(rv.Kind())) && rvIsNil(rv) {
+ return
+ }
+ // var canDecode bool
+ switch v := iv.(type) {
+ case *string:
+ *v = ""
+ case *bool:
+ *v = false
+ case *int:
+ *v = 0
+ case *int8:
+ *v = 0
+ case *int16:
+ *v = 0
+ case *int32:
+ *v = 0
+ case *int64:
+ *v = 0
+ case *uint:
+ *v = 0
+ case *uint8:
+ *v = 0
+ case *uint16:
+ *v = 0
+ case *uint32:
+ *v = 0
+ case *uint64:
+ *v = 0
+ case *float32:
+ *v = 0
+ case *float64:
+ *v = 0
+ case *complex64:
+ *v = 0
+ case *complex128:
+ *v = 0
+ case *[]byte:
+ *v = nil
+ case *Raw:
+ *v = nil
+ case *time.Time:
+ *v = time.Time{}
+ case reflect.Value:
+ decSetNonNilRV2Zero(v)
+ default:
+ if !fastpathDecodeSetZeroTypeSwitch(iv) {
+ decSetNonNilRV2Zero(rv)
+ }
+ }
+}
+
+// decSetNonNilRV2Zero will set the non-nil value to its zero value.
+func decSetNonNilRV2Zero(v reflect.Value) {
+ // If not decodeable (settable), we do not touch it.
+ // We considered empty'ing it if not decodeable e.g.
+ // - if chan, drain it
+ // - if map, clear it
+ // - if slice or array, zero all elements up to len
+ //
+ // However, we decided instead that we either will set the
+ // whole value to the zero value, or leave AS IS.
+
+ k := v.Kind()
+ if k == reflect.Interface {
+ decSetNonNilRV2Zero4Intf(v)
+ } else if k == reflect.Ptr {
+ decSetNonNilRV2Zero4Ptr(v)
+ } else if v.CanSet() {
+ rvSetDirectZero(v)
+ }
+}
+
+func decSetNonNilRV2Zero4Ptr(v reflect.Value) {
+ ve := v.Elem()
+ if ve.CanSet() {
+ rvSetZero(ve) // we can have a pointer to an interface
+ } else if v.CanSet() {
+ rvSetZero(v)
+ }
+}
+
+func decSetNonNilRV2Zero4Intf(v reflect.Value) {
+ ve := v.Elem()
+ if ve.CanSet() {
+ rvSetDirectZero(ve) // interfaces always have element as a non-interface
+ } else if v.CanSet() {
+ rvSetZero(v)
+ }
+}
+
+func (d *decoderBase) arrayCannotExpand(sliceLen, streamLen int) {
+ if d.h.ErrorIfNoArrayExpand {
+ halt.errorf("cannot expand array len during decode from %v to %v", any(sliceLen), any(streamLen))
+ }
+}
+
+//go:noinline
+func (d *decoderBase) haltAsNotDecodeable(rv reflect.Value) {
+ if !rv.IsValid() {
+ halt.onerror(errCannotDecodeIntoNil)
+ }
+ // check if an interface can be retrieved, before grabbing an interface
+ if !rv.CanInterface() {
+ halt.errorf("cannot decode into a value without an interface: %v", rv)
+ }
+ halt.errorf("cannot decode into value of kind: %v, %#v", rv.Kind(), rv2i(rv))
+}
+
+func (d *decoderBase) depthIncr() {
+ d.depth++
+ if d.depth >= d.maxdepth {
+ halt.onerror(errMaxDepthExceeded)
+ }
+}
+
+func (d *decoderBase) depthDecr() {
+ d.depth--
+}
+
+func (d *decoderBase) arrayStart(v int) int {
+ if v != containerLenNil {
+ d.depthIncr()
+ d.c = containerArrayStart
+ }
+ return v
+}
+
+func (d *decoderBase) oneShotAddrRV(rvt reflect.Type, rvk reflect.Kind) reflect.Value {
+ // MARKER 2025: is this slow for calling oneShot?
+ if decUseTransient && d.h.getTypeInfo4RT(baseRT(rvt)).flagCanTransient {
+ return d.perType.TransientAddrK(rvt, rvk)
+ }
+ return rvZeroAddrK(rvt, rvk)
+}
+
+// decNegintPosintFloatNumberHelper is used for formats that are binary
+// and have distinct ways of storing positive integers vs negative integers
+// vs floats, which are uniquely identified by the byte descriptor.
+//
+// Currently, these formats are binc, cbor and simple.
+type decNegintPosintFloatNumberHelper struct {
+ d decDriverI
+}
+
+func (x decNegintPosintFloatNumberHelper) uint64(ui uint64, neg, ok bool) uint64 {
+ if ok && !neg {
+ return ui
+ }
+ return x.uint64TryFloat(ok)
+}
+
+func (x decNegintPosintFloatNumberHelper) uint64TryFloat(neg bool) (ui uint64) {
+ if neg { // neg = true
+ halt.errorStr("assigning negative signed value to unsigned type")
+ }
+ f, ok := x.d.decFloat()
+ if !(ok && f >= 0 && noFrac64(math.Float64bits(f))) {
+ halt.errorStr2("invalid number loading uint64, with descriptor: ", x.d.descBd())
+ }
+ return uint64(f)
+}
+
+func (x decNegintPosintFloatNumberHelper) int64(ui uint64, neg, ok, cbor bool) (i int64) {
+ if ok {
+ return decNegintPosintFloatNumberHelperInt64v(ui, neg, cbor)
+ }
+ // return x.int64TryFloat()
+ // }
+ // func (x decNegintPosintFloatNumberHelper) int64TryFloat() (i int64) {
+ f, ok := x.d.decFloat()
+ if !(ok && noFrac64(math.Float64bits(f))) {
+ halt.errorf("invalid number loading uint64 (%v), with descriptor: %s", f, x.d.descBd())
+ }
+ return int64(f)
+}
+
+func (x decNegintPosintFloatNumberHelper) float64(f float64, ok, cbor bool) float64 {
+ if ok {
+ return f
+ }
+ return x.float64TryInteger(cbor)
+}
+
+func (x decNegintPosintFloatNumberHelper) float64TryInteger(cbor bool) float64 {
+ ui, neg, ok := x.d.decInteger()
+ if !ok {
+ halt.errorStr2("invalid descriptor for float: ", x.d.descBd())
+ }
+ return float64(decNegintPosintFloatNumberHelperInt64v(ui, neg, cbor))
+}
+
+func decNegintPosintFloatNumberHelperInt64v(ui uint64, neg, incrIfNeg bool) (i int64) {
+ if neg && incrIfNeg {
+ ui++
+ }
+ i = chkOvf.SignedIntV(ui)
+ if neg {
+ i = -i
+ }
+ return
+}
+
+// isDecodeable checks if value can be decoded into
+//
+// decode can take any reflect.Value that is a inherently addressable i.e.
+// - non-nil chan (we will SEND to it)
+// - non-nil slice (we will set its elements)
+// - non-nil map (we will put into it)
+// - non-nil pointer (we can "update" it)
+// - func: no
+// - interface: no
+// - array: if canAddr=true
+// - any other value pointer: if canAddr=true
+func isDecodeable(rv reflect.Value) (canDecode bool, reason decNotDecodeableReason) {
+ switch rv.Kind() {
+ case reflect.Ptr, reflect.Slice, reflect.Chan, reflect.Map:
+ canDecode = !rvIsNil(rv)
+ reason = decNotDecodeableReasonNilReference
+ case reflect.Func, reflect.Interface, reflect.Invalid, reflect.UnsafePointer:
+ reason = decNotDecodeableReasonBadKind
+ default:
+ canDecode = rv.CanAddr()
+ reason = decNotDecodeableReasonNonAddrValue
+ }
+ return
+}
+
+// decInferLen will infer a sensible length, given the following:
+// - clen: length wanted.
+// - maxlen: max length to be returned.
+// if <= 0, it is unset, and we infer it based on the unit size
+// - unit: number of bytes for each element of the collection
+func decInferLen(clen int, maxlen, unit uint) (n uint) {
+ // anecdotal testing showed increase in allocation with map length of 16.
+ // We saw same typical alloc from 0-8, then a 20% increase at 16.
+ // Thus, we set it to 8.
+
+ const (
+ minLenIfUnset = 8
+ maxMem = 1024 * 1024 // 1 MB Memory
+ )
+
+ // handle when maxlen is not set i.e. <= 0
+
+ // clen==0: use 0
+ // maxlen<=0, clen<0: use default
+ // maxlen> 0, clen<0: use default
+ // maxlen<=0, clen>0: infer maxlen, and cap on it
+ // maxlen> 0, clen>0: cap at maxlen
+
+ if clen == 0 || clen == containerLenNil {
+ return 0
+ }
+ if clen < 0 {
+ // if unspecified, return 64 for bytes, ... 8 for uint64, ... and everything else
+ return max(64/unit, minLenIfUnset)
+ }
+ if unit == 0 {
+ return uint(clen)
+ }
+ if maxlen == 0 {
+ maxlen = maxMem / unit
+ }
+ return min(uint(clen), maxlen)
+}
+
+type Decoder struct {
+ decoderI
+}
+
+// NewDecoder returns a Decoder for decoding a stream of bytes from an io.Reader.
+//
+// For efficiency, Users are encouraged to configure ReaderBufferSize on the handle
+// OR pass in a memory buffered reader (eg bufio.Reader, bytes.Buffer).
+func NewDecoder(r io.Reader, h Handle) *Decoder {
+ return &Decoder{h.newDecoder(r)}
+}
+
+// NewDecoderBytes returns a Decoder which efficiently decodes directly
+// from a byte slice with zero copying.
+func NewDecoderBytes(in []byte, h Handle) *Decoder {
+ return &Decoder{h.newDecoderBytes(in)}
+}
+
+// NewDecoderString returns a Decoder which efficiently decodes directly
+// from a string with zero copying.
+//
+// It is a convenience function that calls NewDecoderBytes with a
+// []byte view into the string.
+//
+// This can be an efficient zero-copy if using default mode i.e. without codec.safe tag.
+func NewDecoderString(s string, h Handle) *Decoder {
+ return NewDecoderBytes(bytesView(s), h)
+}
+
+// ----
+
+func sideDecode(h Handle, p *sync.Pool, fn func(decoderI)) {
+ var s decoderI
+ if usePoolForSideDecode {
+ s = p.Get().(decoderI)
+ defer p.Put(s)
+ } else {
+ // initialization cycle error
+ // s = NewDecoderBytes(nil, h).decoderI
+ s = p.New().(decoderI)
+ }
+ fn(s)
+}
+
+func oneOffDecode(sd decoderI, v interface{}, in []byte, basetype reflect.Type, ext bool) {
+ sd.ResetBytes(in)
+ sd.decodeAs(v, basetype, ext)
+ // d.sideDecoder(xbs)
+ // d.sideDecode(rv, basetype)
+}
+
+func bytesOKdbi(v []byte, _ dBytesIntoState) []byte {
+ return v
+}
+
+func bytesOKs(bs []byte, _ dBytesAttachState) []byte {
+ return bs
+}