mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 19:12:25 -06:00 
			
		
		
		
	- 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>
		
	
			
		
			
				
	
	
		
			944 lines
		
	
	
	
		
			28 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			944 lines
		
	
	
	
		
			28 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// 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
 | 
						|
}
 |