// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build goexperiment.jsonv2

package json

import (
	"bytes"
	"cmp"
	"encoding"
	"encoding/base32"
	"encoding/base64"
	"encoding/hex"
	"errors"
	"fmt"
	"math"
	"reflect"
	"slices"
	"strconv"
	"strings"
	"sync"

	"encoding/json/internal"
	"encoding/json/internal/jsonflags"
	"encoding/json/internal/jsonopts"
	"encoding/json/internal/jsonwire"
	"encoding/json/jsontext"
)

// optimizeCommon specifies whether to use optimizations targeted for certain
// common patterns, rather than using the slower, but more general logic.
// All tests should pass regardless of whether this is true or not.
const optimizeCommon = true

var (
	// Most natural Go types that correspond with each JSON type.
	anyType          = reflect.TypeFor[any]()            // JSON value
	boolType         = reflect.TypeFor[bool]()           // JSON bool
	stringType       = reflect.TypeFor[string]()         // JSON string
	float64Type      = reflect.TypeFor[float64]()        // JSON number
	mapStringAnyType = reflect.TypeFor[map[string]any]() // JSON object
	sliceAnyType     = reflect.TypeFor[[]any]()          // JSON array

	bytesType       = reflect.TypeFor[[]byte]()
	emptyStructType = reflect.TypeFor[struct{}]()
)

const startDetectingCyclesAfter = 1000

type seenPointers = map[any]struct{}

type typedPointer struct {
	typ reflect.Type
	ptr any // always stores unsafe.Pointer, but avoids depending on unsafe
	len int // remember slice length to avoid false positives
}

// visitPointer visits pointer p of type t, reporting an error if seen before.
// If successfully visited, then the caller must eventually call leave.
func visitPointer(m *seenPointers, v reflect.Value) error {
	p := typedPointer{v.Type(), v.UnsafePointer(), sliceLen(v)}
	if _, ok := (*m)[p]; ok {
		return internal.ErrCycle
	}
	if *m == nil {
		*m = make(seenPointers)
	}
	(*m)[p] = struct{}{}
	return nil
}
func leavePointer(m *seenPointers, v reflect.Value) {
	p := typedPointer{v.Type(), v.UnsafePointer(), sliceLen(v)}
	delete(*m, p)
}

func sliceLen(v reflect.Value) int {
	if v.Kind() == reflect.Slice {
		return v.Len()
	}
	return 0
}

func len64[Bytes ~[]byte | ~string](in Bytes) int64 {
	return int64(len(in))
}

func makeDefaultArshaler(t reflect.Type) *arshaler {
	switch t.Kind() {
	case reflect.Bool:
		return makeBoolArshaler(t)
	case reflect.String:
		return makeStringArshaler(t)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return makeIntArshaler(t)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return makeUintArshaler(t)
	case reflect.Float32, reflect.Float64:
		return makeFloatArshaler(t)
	case reflect.Map:
		return makeMapArshaler(t)
	case reflect.Struct:
		return makeStructArshaler(t)
	case reflect.Slice:
		fncs := makeSliceArshaler(t)
		if t.Elem().Kind() == reflect.Uint8 {
			return makeBytesArshaler(t, fncs)
		}
		return fncs
	case reflect.Array:
		fncs := makeArrayArshaler(t)
		if t.Elem().Kind() == reflect.Uint8 {
			return makeBytesArshaler(t, fncs)
		}
		return fncs
	case reflect.Pointer:
		return makePointerArshaler(t)
	case reflect.Interface:
		return makeInterfaceArshaler(t)
	default:
		return makeInvalidArshaler(t)
	}
}

func makeBoolArshaler(t reflect.Type) *arshaler {
	var fncs arshaler
	fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
		xe := export.Encoder(enc)
		var stringify bool // always false except `string` tag with StringifyWithLegacySemantics
		if mo.Flags.Has(jsonflags.TagFlags) {
			stringify = mo.Flags.Get(jsonflags.StringTag) && mo.Flags.Get(jsonflags.StringifyWithLegacySemantics)
			if mo.Flags.Get(jsonflags.StringTag) && !mo.Flags.Get(jsonflags.StringifyWithLegacySemantics|jsonflags.ReportErrorsWithLegacySemantics) {
				return newMarshalErrorBefore(enc, t, errInvalidStringTag)
			}
			if mo.Flags.Has(jsonflags.FormatTag) {
				return newInvalidFormatError(enc, t)
			}
		}

		// Optimize for marshaling without preceding whitespace.
		if optimizeCommon && !mo.Flags.Get(jsonflags.AnyWhitespace) && !stringify && !xe.Tokens.Last.NeedObjectName() {
			xe.Buf = strconv.AppendBool(xe.Tokens.MayAppendDelim(xe.Buf, 't'), va.Bool())
			xe.Tokens.Last.Increment()
			if xe.NeedFlush() {
				return xe.Flush()
			}
			return nil
		}

		if stringify {
			if va.Bool() {
				return enc.WriteToken(jsontext.String("true"))
			} else {
				return enc.WriteToken(jsontext.String("false"))
			}
		}
		return enc.WriteToken(jsontext.Bool(va.Bool()))
	}
	fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
		var stringify bool // always false except `string` tag with StringifyWithLegacySemantics
		if uo.Flags.Has(jsonflags.TagFlags) {
			stringify = uo.Flags.Get(jsonflags.StringTag) && uo.Flags.Get(jsonflags.StringifyWithLegacySemantics)
			if uo.Flags.Get(jsonflags.StringTag) && !uo.Flags.Get(jsonflags.StringifyWithLegacySemantics|jsonflags.ReportErrorsWithLegacySemantics) {
				return newUnmarshalErrorBeforeWithSkipping(dec, t, errInvalidStringTag)
			}
			if uo.Flags.Has(jsonflags.FormatTag) {
				return newInvalidFormatError(dec, t)
			}
		}
		tok, err := dec.ReadToken()
		if err != nil {
			return err
		}
		k := tok.Kind()
		switch k {
		case 'n':
			if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
				va.SetBool(false)
			}
			return nil
		case 't', 'f':
			if !stringify {
				va.SetBool(tok.Bool())
				return nil
			}
		case '"':
			if stringify {
				switch tok.String() {
				case "true":
					va.SetBool(true)
				case "false":
					va.SetBool(false)
				default:
					if uo.Flags.Get(jsonflags.StringifyWithLegacySemantics) && tok.String() == "null" {
						if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
							va.SetBool(false)
						}
						return nil
					}
					return newUnmarshalErrorAfterWithValue(dec, t, strconv.ErrSyntax)
				}
				return nil
			}
		}
		return newUnmarshalErrorAfterWithSkipping(dec, t, nil)
	}
	return &fncs
}

func makeStringArshaler(t reflect.Type) *arshaler {
	var fncs arshaler
	fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
		xe := export.Encoder(enc)
		var stringify bool // always false except `string` tag with StringifyWithLegacySemantics
		if mo.Flags.Has(jsonflags.TagFlags) {
			stringify = mo.Flags.Get(jsonflags.StringTag) && mo.Flags.Get(jsonflags.StringifyWithLegacySemantics)
			if mo.Flags.Get(jsonflags.StringTag) && !mo.Flags.Get(jsonflags.StringifyWithLegacySemantics|jsonflags.ReportErrorsWithLegacySemantics) {
				return newMarshalErrorBefore(enc, t, errInvalidStringTag)
			}
			if mo.Flags.Has(jsonflags.FormatTag) {
				return newInvalidFormatError(enc, t)
			}
		}

		// Optimize for marshaling without preceding whitespace.
		s := va.String()
		if optimizeCommon && !mo.Flags.Get(jsonflags.AnyWhitespace) && !stringify && !xe.Tokens.Last.NeedObjectName() {
			b := xe.Buf
			b = xe.Tokens.MayAppendDelim(b, '"')
			b, err := jsonwire.AppendQuote(b, []byte(s), &mo.Flags)
			if err == nil {
				xe.Buf = b
				xe.Tokens.Last.Increment()
				if xe.NeedFlush() {
					return xe.Flush()
				}
				return nil
			}
			// Otherwise, the string contains invalid UTF-8,
			// so let the logic below construct the proper error.
		}

		if stringify {
			b, err := jsonwire.AppendQuote(nil, []byte(s), &mo.Flags)
			if err != nil {
				return newMarshalErrorBefore(enc, t, &jsontext.SyntacticError{Err: err})
			}
			q, err := jsontext.AppendQuote(nil, b)
			if err != nil {
				panic("BUG: second AppendQuote should never fail: " + err.Error())
			}
			return enc.WriteValue(q)
		}
		return enc.WriteToken(jsontext.String(s))
	}
	fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
		xd := export.Decoder(dec)
		var stringify bool // always false except `string` tag with StringifyWithLegacySemantics
		if uo.Flags.Has(jsonflags.TagFlags) {
			stringify = uo.Flags.Get(jsonflags.StringTag) && uo.Flags.Get(jsonflags.StringifyWithLegacySemantics)
			if uo.Flags.Get(jsonflags.StringTag) && !uo.Flags.Get(jsonflags.StringifyWithLegacySemantics|jsonflags.ReportErrorsWithLegacySemantics) {
				return newUnmarshalErrorBeforeWithSkipping(dec, t, errInvalidStringTag)
			}
			if uo.Flags.Has(jsonflags.FormatTag) {
				return newInvalidFormatError(dec, t)
			}
		}
		var flags jsonwire.ValueFlags
		val, err := xd.ReadValue(&flags)
		if err != nil {
			return err
		}
		k := val.Kind()
		switch k {
		case 'n':
			if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
				va.SetString("")
			}
			return nil
		case '"':
			val = jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
			if stringify {
				val, err = jsontext.AppendUnquote(nil, val)
				if err != nil {
					return newUnmarshalErrorAfter(dec, t, err)
				}
				if uo.Flags.Get(jsonflags.StringifyWithLegacySemantics) && string(val) == "null" {
					if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
						va.SetString("")
					}
					return nil
				}
			}
			if xd.StringCache == nil {
				xd.StringCache = new(stringCache)
			}
			str := makeString(xd.StringCache, val)
			va.SetString(str)
			return nil
		}
		return newUnmarshalErrorAfter(dec, t, nil)
	}
	return &fncs
}

var (
	appendEncodeBase16    = hex.AppendEncode
	appendEncodeBase32    = base32.StdEncoding.AppendEncode
	appendEncodeBase32Hex = base32.HexEncoding.AppendEncode
	appendEncodeBase64    = base64.StdEncoding.AppendEncode
	appendEncodeBase64URL = base64.URLEncoding.AppendEncode
	encodedLenBase16      = hex.EncodedLen
	encodedLenBase32      = base32.StdEncoding.EncodedLen
	encodedLenBase32Hex   = base32.HexEncoding.EncodedLen
	encodedLenBase64      = base64.StdEncoding.EncodedLen
	encodedLenBase64URL   = base64.URLEncoding.EncodedLen
	appendDecodeBase16    = hex.AppendDecode
	appendDecodeBase32    = base32.StdEncoding.AppendDecode
	appendDecodeBase32Hex = base32.HexEncoding.AppendDecode
	appendDecodeBase64    = base64.StdEncoding.AppendDecode
	appendDecodeBase64URL = base64.URLEncoding.AppendDecode
)

func makeBytesArshaler(t reflect.Type, fncs *arshaler) *arshaler {
	// NOTE: This handles both []~byte and [N]~byte.
	// The v2 default is to treat a []namedByte as equivalent to []T
	// since being able to convert []namedByte to []byte relies on
	// dubious Go reflection behavior (see https://go.dev/issue/24746).
	// For v1 emulation, we use jsonflags.FormatBytesWithLegacySemantics
	// to forcibly treat []namedByte as a []byte.
	marshalArray := fncs.marshal
	isNamedByte := t.Elem().PkgPath() != ""
	hasMarshaler := implementsAny(t.Elem(), allMarshalerTypes...)
	fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
		if !mo.Flags.Get(jsonflags.FormatBytesWithLegacySemantics) && isNamedByte {
			return marshalArray(enc, va, mo) // treat as []T or [N]T
		}
		xe := export.Encoder(enc)
		appendEncode := appendEncodeBase64
		if mo.Flags.Has(jsonflags.TagFlags | jsonflags.FormatByteArrayAsArray | jsonflags.FormatBytesWithLegacySemantics | jsonflags.FormatNilSliceAsNull) {
			switch {
			case mo.Flags.Get(jsonflags.StringTag) && !mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics):
				return newMarshalErrorBefore(enc, t, errInvalidStringTag)
			case mo.Flags.Has(jsonflags.FormatTag):
				switch mo.Format {
				case "base64":
					appendEncode = appendEncodeBase64
				case "base64url":
					appendEncode = appendEncodeBase64URL
				case "base32":
					appendEncode = appendEncodeBase32
				case "base32hex":
					appendEncode = appendEncodeBase32Hex
				case "base16", "hex":
					appendEncode = appendEncodeBase16
				case "array":
					mo.Flags.Clear(jsonflags.FormatTag)
					return marshalArray(enc, va, mo)
				default:
					return newInvalidFormatError(enc, t)
				}
			case mo.Flags.Get(jsonflags.FormatByteArrayAsArray) && va.Kind() == reflect.Array:
				return marshalArray(enc, va, mo)
			case mo.Flags.Get(jsonflags.FormatBytesWithLegacySemantics) && hasMarshaler:
				return marshalArray(enc, va, mo)
			}
			if mo.Flags.Get(jsonflags.FormatNilSliceAsNull) && va.Kind() == reflect.Slice && va.IsNil() {
				// TODO: Provide an "emitempty" format override?
				return enc.WriteToken(jsontext.Null)
			}
		}
		return xe.AppendRaw('"', true, func(b []byte) ([]byte, error) {
			return appendEncode(b, va.Bytes()), nil
		})
	}
	unmarshalArray := fncs.unmarshal
	fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
		if !uo.Flags.Get(jsonflags.FormatBytesWithLegacySemantics) && isNamedByte {
			return unmarshalArray(dec, va, uo) // treat as []T or [N]T
		}
		xd := export.Decoder(dec)
		appendDecode, encodedLen := appendDecodeBase64, encodedLenBase64
		if uo.Flags.Has(jsonflags.TagFlags | jsonflags.FormatByteArrayAsArray | jsonflags.FormatBytesWithLegacySemantics) {
			switch {
			case uo.Flags.Get(jsonflags.StringTag) && !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics):
				return newUnmarshalErrorBeforeWithSkipping(dec, t, errInvalidStringTag)
			case uo.Flags.Has(jsonflags.FormatTag):
				switch uo.Format {
				case "base64":
					appendDecode, encodedLen = appendDecodeBase64, encodedLenBase64
				case "base64url":
					appendDecode, encodedLen = appendDecodeBase64URL, encodedLenBase64URL
				case "base32":
					appendDecode, encodedLen = appendDecodeBase32, encodedLenBase32
				case "base32hex":
					appendDecode, encodedLen = appendDecodeBase32Hex, encodedLenBase32Hex
				case "base16", "hex":
					appendDecode, encodedLen = appendDecodeBase16, encodedLenBase16
				case "array":
					uo.Flags.Clear(jsonflags.FormatTag)
					return unmarshalArray(dec, va, uo)
				default:
					return newInvalidFormatError(dec, t)
				}
			case uo.Flags.Get(jsonflags.FormatByteArrayAsArray) && va.Kind() == reflect.Array:
				return unmarshalArray(dec, va, uo)
			case uo.Flags.Get(jsonflags.FormatBytesWithLegacySemantics) && dec.PeekKind() == '[':
				return unmarshalArray(dec, va, uo)
			}
		}
		var flags jsonwire.ValueFlags
		val, err := xd.ReadValue(&flags)
		if err != nil {
			return err
		}
		k := val.Kind()
		switch k {
		case 'n':
			if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) || va.Kind() != reflect.Array {
				va.SetZero()
			}
			return nil
		case '"':
			// NOTE: The v2 default is to strictly comply with RFC 4648.
			// Section 3.2 specifies that padding is required.
			// Section 3.3 specifies that non-alphabet characters
			// (e.g., '\r' or '\n') must be rejected.
			// Section 3.5 specifies that unnecessary non-zero bits in
			// the last quantum may be rejected. Since this is optional,
			// we do not reject such inputs.
			val = jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
			b, err := appendDecode(va.Bytes()[:0], val)
			if err != nil {
				return newUnmarshalErrorAfter(dec, t, err)
			}
			if len(val) != encodedLen(len(b)) && !uo.Flags.Get(jsonflags.ParseBytesWithLooseRFC4648) {
				// TODO(https://go.dev/issue/53845): RFC 4648, section 3.3,
				// specifies that non-alphabet characters must be rejected.
				// Unfortunately, the "base32" and "base64" packages allow
				// '\r' and '\n' characters by default.
				i := bytes.IndexAny(val, "\r\n")
				err := fmt.Errorf("illegal character %s at offset %d", jsonwire.QuoteRune(val[i:]), i)
				return newUnmarshalErrorAfter(dec, t, err)
			}

			if va.Kind() == reflect.Array {
				dst := va.Bytes()
				clear(dst[copy(dst, b):]) // noop if len(b) >= len(dst)
				if len(b) != len(dst) && !uo.Flags.Get(jsonflags.UnmarshalArrayFromAnyLength) {
					err := fmt.Errorf("decoded length of %d mismatches array length of %d", len(b), len(dst))
					return newUnmarshalErrorAfter(dec, t, err)
				}
			} else {
				if b == nil {
					b = []byte{}
				}
				va.SetBytes(b)
			}
			return nil
		}
		return newUnmarshalErrorAfter(dec, t, nil)
	}
	return fncs
}

func makeIntArshaler(t reflect.Type) *arshaler {
	var fncs arshaler
	bits := t.Bits()
	fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
		xe := export.Encoder(enc)
		stringify := xe.Tokens.Last.NeedObjectName() || mo.Flags.Get(jsonflags.StringifyNumbers|jsonflags.StringTag)
		if mo.Flags.Has(jsonflags.FormatTag) {
			return newInvalidFormatError(enc, t)
		}

		// Optimize for marshaling without preceding whitespace or string escaping.
		if optimizeCommon && !mo.Flags.Get(jsonflags.AnyWhitespace) && !stringify {
			xe.Buf = strconv.AppendInt(xe.Tokens.MayAppendDelim(xe.Buf, '0'), va.Int(), 10)
			xe.Tokens.Last.Increment()
			if xe.NeedFlush() {
				return xe.Flush()
			}
			return nil
		}

		k := stringOrNumberKind(stringify)
		return xe.AppendRaw(k, true, func(b []byte) ([]byte, error) {
			return strconv.AppendInt(b, va.Int(), 10), nil
		})
	}
	fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
		xd := export.Decoder(dec)
		stringify := xd.Tokens.Last.NeedObjectName() || uo.Flags.Get(jsonflags.StringifyNumbers|jsonflags.StringTag)
		if uo.Flags.Has(jsonflags.FormatTag) {
			return newInvalidFormatError(dec, t)
		}
		var flags jsonwire.ValueFlags
		val, err := xd.ReadValue(&flags)
		if err != nil {
			return err
		}
		k := val.Kind()
		switch k {
		case 'n':
			if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
				va.SetInt(0)
			}
			return nil
		case '"':
			if !stringify {
				break
			}
			val = jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
			if uo.Flags.Get(jsonflags.StringifyWithLegacySemantics) {
				// For historical reasons, v1 parsed a quoted number
				// according to the Go syntax and permitted a quoted null.
				// See https://go.dev/issue/75619
				n, err := strconv.ParseInt(string(val), 10, bits)
				if err != nil {
					if string(val) == "null" {
						if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
							va.SetInt(0)
						}
						return nil
					}
					return newUnmarshalErrorAfterWithValue(dec, t, errors.Unwrap(err))
				}
				va.SetInt(n)
				return nil
			}
			fallthrough
		case '0':
			if stringify && k == '0' {
				break
			}
			var negOffset int
			neg := len(val) > 0 && val[0] == '-'
			if neg {
				negOffset = 1
			}
			n, ok := jsonwire.ParseUint(val[negOffset:])
			maxInt := uint64(1) << (bits - 1)
			overflow := (neg && n > maxInt) || (!neg && n > maxInt-1)
			if !ok {
				if n != math.MaxUint64 {
					return newUnmarshalErrorAfterWithValue(dec, t, strconv.ErrSyntax)
				}
				overflow = true
			}
			if overflow {
				return newUnmarshalErrorAfterWithValue(dec, t, strconv.ErrRange)
			}
			if neg {
				va.SetInt(int64(-n))
			} else {
				va.SetInt(int64(+n))
			}
			return nil
		}
		return newUnmarshalErrorAfter(dec, t, nil)
	}
	return &fncs
}

func makeUintArshaler(t reflect.Type) *arshaler {
	var fncs arshaler
	bits := t.Bits()
	fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
		xe := export.Encoder(enc)
		stringify := xe.Tokens.Last.NeedObjectName() || mo.Flags.Get(jsonflags.StringifyNumbers|jsonflags.StringTag)
		if mo.Flags.Has(jsonflags.FormatTag) {
			return newInvalidFormatError(enc, t)
		}

		// Optimize for marshaling without preceding whitespace or string escaping.
		if optimizeCommon && !mo.Flags.Get(jsonflags.AnyWhitespace) && !stringify {
			xe.Buf = strconv.AppendUint(xe.Tokens.MayAppendDelim(xe.Buf, '0'), va.Uint(), 10)
			xe.Tokens.Last.Increment()
			if xe.NeedFlush() {
				return xe.Flush()
			}
			return nil
		}

		k := stringOrNumberKind(stringify)
		return xe.AppendRaw(k, true, func(b []byte) ([]byte, error) {
			return strconv.AppendUint(b, va.Uint(), 10), nil
		})
	}
	fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
		xd := export.Decoder(dec)
		stringify := xd.Tokens.Last.NeedObjectName() || uo.Flags.Get(jsonflags.StringifyNumbers|jsonflags.StringTag)
		if uo.Flags.Has(jsonflags.FormatTag) {
			return newInvalidFormatError(dec, t)
		}
		var flags jsonwire.ValueFlags
		val, err := xd.ReadValue(&flags)
		if err != nil {
			return err
		}
		k := val.Kind()
		switch k {
		case 'n':
			if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
				va.SetUint(0)
			}
			return nil
		case '"':
			if !stringify {
				break
			}
			val = jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
			if uo.Flags.Get(jsonflags.StringifyWithLegacySemantics) {
				// For historical reasons, v1 parsed a quoted number
				// according to the Go syntax and permitted a quoted null.
				// See https://go.dev/issue/75619
				n, err := strconv.ParseUint(string(val), 10, bits)
				if err != nil {
					if string(val) == "null" {
						if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
							va.SetUint(0)
						}
						return nil
					}
					return newUnmarshalErrorAfterWithValue(dec, t, errors.Unwrap(err))
				}
				va.SetUint(n)
				return nil
			}
			fallthrough
		case '0':
			if stringify && k == '0' {
				break
			}
			n, ok := jsonwire.ParseUint(val)
			maxUint := uint64(1) << bits
			overflow := n > maxUint-1
			if !ok {
				if n != math.MaxUint64 {
					return newUnmarshalErrorAfterWithValue(dec, t, strconv.ErrSyntax)
				}
				overflow = true
			}
			if overflow {
				return newUnmarshalErrorAfterWithValue(dec, t, strconv.ErrRange)
			}
			va.SetUint(n)
			return nil
		}
		return newUnmarshalErrorAfter(dec, t, nil)
	}
	return &fncs
}

func makeFloatArshaler(t reflect.Type) *arshaler {
	var fncs arshaler
	bits := t.Bits()
	fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
		xe := export.Encoder(enc)
		stringify := xe.Tokens.Last.NeedObjectName() || mo.Flags.Get(jsonflags.StringifyNumbers|jsonflags.StringTag)
		var allowNonFinite bool
		if mo.Flags.Has(jsonflags.FormatTag) {
			if mo.Format == "nonfinite" {
				allowNonFinite = true
			} else {
				return newInvalidFormatError(enc, t)
			}
		}

		fv := va.Float()
		if math.IsNaN(fv) || math.IsInf(fv, 0) {
			if !allowNonFinite {
				err := fmt.Errorf("unsupported value: %v", fv)
				return newMarshalErrorBefore(enc, t, err)
			}
			return enc.WriteToken(jsontext.Float(fv))
		}

		// Optimize for marshaling without preceding whitespace or string escaping.
		if optimizeCommon && !mo.Flags.Get(jsonflags.AnyWhitespace) && !stringify {
			xe.Buf = jsonwire.AppendFloat(xe.Tokens.MayAppendDelim(xe.Buf, '0'), fv, bits)
			xe.Tokens.Last.Increment()
			if xe.NeedFlush() {
				return xe.Flush()
			}
			return nil
		}

		k := stringOrNumberKind(stringify)
		return xe.AppendRaw(k, true, func(b []byte) ([]byte, error) {
			return jsonwire.AppendFloat(b, va.Float(), bits), nil
		})
	}
	fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
		xd := export.Decoder(dec)
		stringify := xd.Tokens.Last.NeedObjectName() || uo.Flags.Get(jsonflags.StringifyNumbers|jsonflags.StringTag)
		var allowNonFinite bool
		if uo.Flags.Has(jsonflags.FormatTag) {
			if uo.Format == "nonfinite" {
				allowNonFinite = true
			} else {
				return newInvalidFormatError(dec, t)
			}
		}

		var flags jsonwire.ValueFlags
		val, err := xd.ReadValue(&flags)
		if err != nil {
			return err
		}
		k := val.Kind()
		switch k {
		case 'n':
			if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
				va.SetFloat(0)
			}
			return nil
		case '"':
			val = jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
			if allowNonFinite {
				switch string(val) {
				case "NaN":
					va.SetFloat(math.NaN())
					return nil
				case "Infinity":
					va.SetFloat(math.Inf(+1))
					return nil
				case "-Infinity":
					va.SetFloat(math.Inf(-1))
					return nil
				}
			}
			if !stringify {
				break
			}
			if uo.Flags.Get(jsonflags.StringifyWithLegacySemantics) {
				// For historical reasons, v1 parsed a quoted number
				// according to the Go syntax and permitted a quoted null.
				// See https://go.dev/issue/75619
				n, err := strconv.ParseFloat(string(val), bits)
				if err != nil {
					if string(val) == "null" {
						if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
							va.SetFloat(0)
						}
						return nil
					}
					return newUnmarshalErrorAfterWithValue(dec, t, errors.Unwrap(err))
				}
				va.SetFloat(n)
				return nil
			}
			if n, err := jsonwire.ConsumeNumber(val); n != len(val) || err != nil {
				return newUnmarshalErrorAfterWithValue(dec, t, strconv.ErrSyntax)
			}
			fallthrough
		case '0':
			if stringify && k == '0' {
				break
			}
			fv, err := strconv.ParseFloat(string(val), bits)
			va.SetFloat(fv)
			if err != nil {
				return newUnmarshalErrorAfterWithValue(dec, t, errors.Unwrap(err))
			}
			return nil
		}
		return newUnmarshalErrorAfter(dec, t, nil)
	}
	return &fncs
}

func makeMapArshaler(t reflect.Type) *arshaler {
	// NOTE: The logic below disables namespaces for tracking duplicate names
	// when handling map keys with a unique representation.

	// NOTE: Values retrieved from a map are not addressable,
	// so we shallow copy the values to make them addressable and
	// store them back into the map afterwards.

	var fncs arshaler
	var (
		once    sync.Once
		keyFncs *arshaler
		valFncs *arshaler
	)
	init := func() {
		keyFncs = lookupArshaler(t.Key())
		valFncs = lookupArshaler(t.Elem())
	}
	nillableLegacyKey := t.Key().Kind() == reflect.Pointer &&
		implementsAny(t.Key(), textMarshalerType, textAppenderType)
	fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
		// Check for cycles.
		xe := export.Encoder(enc)
		if xe.Tokens.Depth() > startDetectingCyclesAfter {
			if err := visitPointer(&xe.SeenPointers, va.Value); err != nil {
				return newMarshalErrorBefore(enc, t, err)
			}
			defer leavePointer(&xe.SeenPointers, va.Value)
		}

		emitNull := mo.Flags.Get(jsonflags.FormatNilMapAsNull)
		if mo.Flags.Has(jsonflags.TagFlags) {
			if mo.Flags.Get(jsonflags.StringTag) && !mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
				return newMarshalErrorBefore(enc, t, errInvalidStringTag)
			}
			if mo.Flags.Has(jsonflags.FormatTag) {
				switch mo.Format {
				case "emitnull":
					emitNull = true
				case "emitempty":
					emitNull = false
				default:
					return newInvalidFormatError(enc, t)
				}
			}
		}

		// Handle empty maps.
		n := va.Len()
		if n == 0 {
			if emitNull && va.IsNil() {
				return enc.WriteToken(jsontext.Null)
			}
			// Optimize for marshaling an empty map without any preceding whitespace.
			if optimizeCommon && !mo.Flags.Get(jsonflags.AnyWhitespace) && !xe.Tokens.Last.NeedObjectName() {
				xe.Buf = append(xe.Tokens.MayAppendDelim(xe.Buf, '{'), "{}"...)
				xe.Tokens.Last.Increment()
				if xe.NeedFlush() {
					return xe.Flush()
				}
				return nil
			}
		}

		once.Do(init)
		if err := enc.WriteToken(jsontext.BeginObject); err != nil {
			return err
		}
		if n > 0 {
			nonDefaultKey := keyFncs.nonDefault
			marshalKey := keyFncs.marshal
			marshalVal := valFncs.marshal
			if mo.Marshalers != nil {
				var ok bool
				marshalKey, ok = mo.Marshalers.(*Marshalers).lookup(marshalKey, t.Key())
				marshalVal, _ = mo.Marshalers.(*Marshalers).lookup(marshalVal, t.Elem())
				nonDefaultKey = nonDefaultKey || ok
			}
			k := newAddressableValue(t.Key())
			v := newAddressableValue(t.Elem())

			// A Go map guarantees that each entry has a unique key.
			// As such, disable the expensive duplicate name check if we know
			// that every Go key will serialize as a unique JSON string.
			if !nonDefaultKey && mapKeyWithUniqueRepresentation(k.Kind(), mo.Flags.Get(jsonflags.AllowInvalidUTF8)) {
				xe.Tokens.Last.DisableNamespace()
			}

			switch {
			case !mo.Flags.Get(jsonflags.Deterministic) || n <= 1:
				for iter := va.Value.MapRange(); iter.Next(); {
					k.SetIterKey(iter)
					err := marshalKey(enc, k, mo)
					if err != nil {
						if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
							errors.Is(err, jsontext.ErrNonStringName) && nillableLegacyKey && k.IsNil() {
							err = enc.WriteToken(jsontext.String(""))
						}
						if err != nil {
							if serr, ok := err.(*jsontext.SyntacticError); ok && serr.Err == jsontext.ErrNonStringName {
								err = newMarshalErrorBefore(enc, k.Type(), err)
							}
							return err
						}
					}
					v.SetIterValue(iter)
					if err := marshalVal(enc, v, mo); err != nil {
						return err
					}
				}
			case !nonDefaultKey && t.Key().Kind() == reflect.String:
				names := getStrings(n)
				for i, iter := 0, va.Value.MapRange(); i < n && iter.Next(); i++ {
					k.SetIterKey(iter)
					(*names)[i] = k.String()
				}
				slices.Sort(*names)
				for _, name := range *names {
					if err := enc.WriteToken(jsontext.String(name)); err != nil {
						return err
					}
					// TODO(https://go.dev/issue/57061): Use v.SetMapIndexOf.
					k.SetString(name)
					v.Set(va.MapIndex(k.Value))
					if err := marshalVal(enc, v, mo); err != nil {
						return err
					}
				}
				putStrings(names)
			default:
				type member struct {
					name string // unquoted name
					key  addressableValue
					val  addressableValue
				}
				members := make([]member, n)
				keys := reflect.MakeSlice(reflect.SliceOf(t.Key()), n, n)
				vals := reflect.MakeSlice(reflect.SliceOf(t.Elem()), n, n)
				for i, iter := 0, va.Value.MapRange(); i < n && iter.Next(); i++ {
					// Marshal the member name.
					k := addressableValue{keys.Index(i), true} // indexed slice element is always addressable
					k.SetIterKey(iter)
					v := addressableValue{vals.Index(i), true} // indexed slice element is always addressable
					v.SetIterValue(iter)
					err := marshalKey(enc, k, mo)
					if err != nil {
						if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
							errors.Is(err, jsontext.ErrNonStringName) && nillableLegacyKey && k.IsNil() {
							err = enc.WriteToken(jsontext.String(""))
						}
						if err != nil {
							if serr, ok := err.(*jsontext.SyntacticError); ok && serr.Err == jsontext.ErrNonStringName {
								err = newMarshalErrorBefore(enc, k.Type(), err)
							}
							return err
						}
					}
					name := xe.UnwriteOnlyObjectMemberName()
					members[i] = member{name, k, v}
				}
				// TODO: If AllowDuplicateNames is enabled, then sort according
				// to reflect.Value as well if the names are equal.
				// See internal/fmtsort.
				slices.SortFunc(members, func(x, y member) int {
					return strings.Compare(x.name, y.name)
				})
				for _, member := range members {
					if err := enc.WriteToken(jsontext.String(member.name)); err != nil {
						return err
					}
					if err := marshalVal(enc, member.val, mo); err != nil {
						return err
					}
				}
			}
		}
		if err := enc.WriteToken(jsontext.EndObject); err != nil {
			return err
		}
		return nil
	}
	fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
		xd := export.Decoder(dec)
		if uo.Flags.Has(jsonflags.TagFlags) {
			if uo.Flags.Get(jsonflags.StringTag) && !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
				return newUnmarshalErrorBeforeWithSkipping(dec, t, errInvalidStringTag)
			}
			if uo.Flags.Has(jsonflags.FormatTag) {
				switch uo.Format {
				case "emitnull", "emitempty":
				default:
					return newInvalidFormatError(dec, t)
				}
			}
		}
		tok, err := dec.ReadToken()
		if err != nil {
			return err
		}
		k := tok.Kind()
		switch k {
		case 'n':
			va.SetZero()
			return nil
		case '{':
			once.Do(init)
			if va.IsNil() {
				va.Set(reflect.MakeMap(t))
			}

			nonDefaultKey := keyFncs.nonDefault
			unmarshalKey := keyFncs.unmarshal
			unmarshalVal := valFncs.unmarshal
			if uo.Unmarshalers != nil {
				var ok bool
				unmarshalKey, ok = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshalKey, t.Key())
				unmarshalVal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshalVal, t.Elem())
				nonDefaultKey = nonDefaultKey || ok
			}
			k := newAddressableValue(t.Key())
			v := newAddressableValue(t.Elem())

			// Manually check for duplicate entries by virtue of whether the
			// unmarshaled key already exists in the destination Go map.
			// Consequently, syntactically different names (e.g., "0" and "-0")
			// will be rejected as duplicates since they semantically refer
			// to the same Go value. This is an unusual interaction
			// between syntax and semantics, but is more correct.
			if !nonDefaultKey && mapKeyWithUniqueRepresentation(k.Kind(), uo.Flags.Get(jsonflags.AllowInvalidUTF8)) {
				xd.Tokens.Last.DisableNamespace()
			}

			// In the rare case where the map is not already empty,
			// then we need to manually track which keys we already saw
			// since existing presence alone is insufficient to indicate
			// whether the input had a duplicate name.
			var seen reflect.Value
			if !uo.Flags.Get(jsonflags.AllowDuplicateNames) && va.Len() > 0 {
				seen = reflect.MakeMap(reflect.MapOf(k.Type(), emptyStructType))
			}

			var errUnmarshal error
			for dec.PeekKind() != '}' {
				// Unmarshal the map entry key.
				k.SetZero()
				err := unmarshalKey(dec, k, uo)
				if err != nil {
					if isFatalError(err, uo.Flags) {
						return err
					}
					if err := dec.SkipValue(); err != nil {
						return err
					}
					errUnmarshal = cmp.Or(errUnmarshal, err)
					continue
				}
				if k.Kind() == reflect.Interface && !k.IsNil() && !k.Elem().Type().Comparable() {
					err := newUnmarshalErrorAfter(dec, t, fmt.Errorf("invalid incomparable key type %v", k.Elem().Type()))
					if !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
						return err
					}
					if err2 := dec.SkipValue(); err2 != nil {
						return err2
					}
					errUnmarshal = cmp.Or(errUnmarshal, err)
					continue
				}

				// Check if a pre-existing map entry value exists for this key.
				if v2 := va.MapIndex(k.Value); v2.IsValid() {
					if !uo.Flags.Get(jsonflags.AllowDuplicateNames) && (!seen.IsValid() || seen.MapIndex(k.Value).IsValid()) {
						// TODO: Unread the object name.
						name := xd.PreviousTokenOrValue()
						return newDuplicateNameError(dec.StackPointer(), nil, dec.InputOffset()-len64(name))
					}
					if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
						v.Set(v2)
					} else {
						v.SetZero()
					}
				} else {
					v.SetZero()
				}

				// Unmarshal the map entry value.
				err = unmarshalVal(dec, v, uo)
				va.SetMapIndex(k.Value, v.Value)
				if seen.IsValid() {
					seen.SetMapIndex(k.Value, reflect.Zero(emptyStructType))
				}
				if err != nil {
					if isFatalError(err, uo.Flags) {
						return err
					}
					errUnmarshal = cmp.Or(errUnmarshal, err)
				}
			}
			if _, err := dec.ReadToken(); err != nil {
				return err
			}
			return errUnmarshal
		}
		return newUnmarshalErrorAfterWithSkipping(dec, t, nil)
	}
	return &fncs
}

// mapKeyWithUniqueRepresentation reports whether all possible values of k
// marshal to a different JSON value, and whether all possible JSON values
// that can unmarshal into k unmarshal to different Go values.
// In other words, the representation must be a bijection.
func mapKeyWithUniqueRepresentation(k reflect.Kind, allowInvalidUTF8 bool) bool {
	switch k {
	case reflect.Bool,
		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return true
	case reflect.String:
		// For strings, we have to be careful since names with invalid UTF-8
		// may unescape to the same Go string value.
		return !allowInvalidUTF8
	default:
		// Floating-point kinds are not listed above since NaNs
		// can appear multiple times and all serialize as "NaN".
		return false
	}
}

var errNilField = errors.New("cannot set embedded pointer to unexported struct type")
var errInvalidStringTag = errors.New("invalid use of `string` tag option")

func makeStructArshaler(t reflect.Type) *arshaler {
	// NOTE: The logic below disables namespaces for tracking duplicate names
	// and does the tracking locally with an efficient bit-set based on which
	// Go struct fields were seen.

	var fncs arshaler
	var (
		once    sync.Once
		fields  structFields
		errInit *SemanticError
	)
	init := func() {
		fields, errInit = makeStructFields(t)
	}
	fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
		xe := export.Encoder(enc)
		if mo.Flags.Has(jsonflags.TagFlags) {
			if mo.Flags.Get(jsonflags.StringTag) && !mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
				return newMarshalErrorBefore(enc, t, errInvalidStringTag)
			}
			if mo.Flags.Has(jsonflags.FormatTag) {
				return newInvalidFormatError(enc, t)
			}
		}
		once.Do(init)
		if errInit != nil && !mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
			return newMarshalErrorBefore(enc, errInit.GoType, errInit.Err)
		} else if fields.errUnsupportedFormat != nil && !mo.Flags.Get(jsonflags.FormatTagSupported) {
			return newMarshalErrorBefore(enc, fields.errUnsupportedFormat.GoType, fields.errUnsupportedFormat.Err)
		}

		if err := enc.WriteToken(jsontext.BeginObject); err != nil {
			return err
		}
		var seenIdxs uintSet
		prevIdx := -1
		xe.Tokens.Last.DisableNamespace() // we manually ensure unique names below
		for i := range fields.flattened {
			f := &fields.flattened[i]
			v := addressableValue{va.Field(f.index0), va.forcedAddr} // addressable if struct value is addressable
			if len(f.index) > 0 {
				v = v.fieldByIndex(f.index, false)
				if !v.IsValid() {
					continue // implies a nil embedded field
				}
			}

			// OmitZero skips the field if the Go value is zero,
			// which we can determine up front without calling the marshaler.
			if (f.omitzero || mo.Flags.Get(jsonflags.OmitZeroStructFields)) &&
				((f.isZero == nil && v.IsZero()) || (f.isZero != nil && f.isZero(v))) {
				continue
			}

			// Check for the legacy definition of omitempty.
			if f.omitempty && mo.Flags.Get(jsonflags.OmitEmptyWithLegacySemantics) && isLegacyEmpty(v) {
				continue
			}

			marshal := f.fncs.marshal
			nonDefault := f.fncs.nonDefault
			if mo.Marshalers != nil {
				var ok bool
				marshal, ok = mo.Marshalers.(*Marshalers).lookup(marshal, f.typ)
				nonDefault = nonDefault || ok
			}

			// OmitEmpty skips the field if the marshaled JSON value is empty,
			// which we can know up front if there are no custom marshalers,
			// otherwise we must marshal the value and unwrite it if empty.
			if f.omitempty && !mo.Flags.Get(jsonflags.OmitEmptyWithLegacySemantics) &&
				!nonDefault && f.isEmpty != nil && f.isEmpty(v) {
				continue // fast path for omitempty
			}

			// Write the object member name.
			//
			// The logic below is semantically equivalent to:
			//	enc.WriteToken(String(f.name))
			// but specialized and simplified because:
			//	1. The Encoder must be expecting an object name.
			//	2. The object namespace is guaranteed to be disabled.
			//	3. The object name is guaranteed to be valid and pre-escaped.
			//	4. There is no need to flush the buffer (for unwrite purposes).
			//	5. There is no possibility of an error occurring.
			if optimizeCommon {
				// Append any delimiters or optional whitespace.
				b := xe.Buf
				if xe.Tokens.Last.Length() > 0 {
					b = append(b, ',')
					if mo.Flags.Get(jsonflags.SpaceAfterComma) {
						b = append(b, ' ')
					}
				}
				if mo.Flags.Get(jsonflags.Multiline) {
					b = xe.AppendIndent(b, xe.Tokens.NeedIndent('"'))
				}

				// Append the token to the output and to the state machine.
				n0 := len(b) // offset before calling AppendQuote
				if !f.nameNeedEscape {
					b = append(b, f.quotedName...)
				} else {
					b, _ = jsonwire.AppendQuote(b, []byte(f.name), &mo.Flags)
				}
				xe.Buf = b
				xe.Names.ReplaceLastQuotedOffset(n0)
				xe.Tokens.Last.Increment()
			} else {
				if err := enc.WriteToken(jsontext.String(f.name)); err != nil {
					return err
				}
			}

			// Write the object member value.
			flagsOriginal := mo.Flags
			if f.string {
				mo.Flags.Set(jsonflags.StringTag | 1)
			}
			if f.format != "" {
				mo.Flags.Set(jsonflags.FormatTag | 1)
				mo.Format = f.format
			}
			err := marshal(enc, v, mo)
			mo.Flags = flagsOriginal
			mo.Format = ""
			if err != nil {
				return err
			}

			// Try unwriting the member if empty (slow path for omitempty).
			if f.omitempty && !mo.Flags.Get(jsonflags.OmitEmptyWithLegacySemantics) {
				var prevName *string
				if prevIdx >= 0 {
					prevName = &fields.flattened[prevIdx].name
				}
				if xe.UnwriteEmptyObjectMember(prevName) {
					continue
				}
			}

			// Remember the previous written object member.
			// The set of seen fields only needs to be updated to detect
			// duplicate names with those from the embedded fallback.
			if !mo.Flags.Get(jsonflags.AllowDuplicateNames) && fields.embeddedFallback != nil {
				seenIdxs.insert(uint(f.id))
			}
			prevIdx = f.id
		}
		if fields.embeddedFallback != nil {
			var insertUnquotedName func([]byte) bool
			if !mo.Flags.Get(jsonflags.AllowDuplicateNames) {
				insertUnquotedName = func(name []byte) bool {
					// Check that the name from embedded fallback does not match
					// one of the previously marshaled names from known fields.
					if foldedFields := fields.lookupByFoldedName(name); len(foldedFields) > 0 {
						if f := fields.byActualName[string(name)]; f != nil {
							return seenIdxs.insert(uint(f.id))
						}
						for _, f := range foldedFields {
							if f.matchFoldedName(name, &mo.Flags) {
								return seenIdxs.insert(uint(f.id))
							}
						}
					}

					// Check that the name does not match any other name
					// previously marshaled from the embedded fallback.
					return xe.Namespaces.Last().InsertUnquoted(name)
				}
			}
			if err := marshalEmbeddedFallbackAll(enc, va, mo, fields.embeddedFallback, insertUnquotedName); err != nil {
				return err
			}
		}
		if err := enc.WriteToken(jsontext.EndObject); err != nil {
			return err
		}
		return nil
	}
	fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
		xd := export.Decoder(dec)
		if uo.Flags.Has(jsonflags.TagFlags) {
			if uo.Flags.Get(jsonflags.StringTag) && !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
				return newUnmarshalErrorBeforeWithSkipping(dec, t, errInvalidStringTag)
			}
			if uo.Flags.Has(jsonflags.FormatTag) {
				return newInvalidFormatError(dec, t)
			}
		}
		tok, err := dec.ReadToken()
		if err != nil {
			return err
		}
		k := tok.Kind()
		switch k {
		case 'n':
			if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
				va.SetZero()
			}
			return nil
		case '{':
			once.Do(init)
			if errInit != nil && !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
				return newUnmarshalErrorAfter(dec, errInit.GoType, errInit.Err)
			} else if fields.errUnsupportedFormat != nil && !uo.Flags.Get(jsonflags.FormatTagSupported) {
				return newUnmarshalErrorAfter(dec, fields.errUnsupportedFormat.GoType, fields.errUnsupportedFormat.Err)
			}

			var seenIdxs uintSet
			xd.Tokens.Last.DisableNamespace()
			var errUnmarshal error
			for dec.PeekKind() != '}' {
				// Process the object member name.
				var flags jsonwire.ValueFlags
				val, err := xd.ReadValue(&flags)
				if err != nil {
					return err
				}
				name := jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
				f := fields.byActualName[string(name)]
				if f == nil {
					for _, f2 := range fields.lookupByFoldedName(name) {
						if f2.matchFoldedName(name, &uo.Flags) {
							f = f2
							break
						}
					}
					if f == nil {
						if uo.Flags.Get(jsonflags.RejectUnknownMembers) && fields.embeddedFallback == nil {
							err := newUnmarshalErrorAfter(dec, t, ErrUnknownName)
							if !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
								return err
							}
							errUnmarshal = cmp.Or(errUnmarshal, err)
						}
						if !uo.Flags.Get(jsonflags.AllowDuplicateNames) && !xd.Namespaces.Last().InsertUnquoted(name) {
							// TODO: Unread the object name.
							return newDuplicateNameError(dec.StackPointer(), nil, dec.InputOffset()-len64(val))
						}

						if fields.embeddedFallback == nil {
							// Skip unknown value since we have no place to store it.
							if err := dec.SkipValue(); err != nil {
								return err
							}
						} else {
							// Unmarshal into a value capable of storing arbitrary object members.
							if err := unmarshalEmbeddedFallbackNext(dec, va, uo, fields.embeddedFallback, val, name); err != nil {
								if isFatalError(err, uo.Flags) {
									return err
								}
								errUnmarshal = cmp.Or(errUnmarshal, err)
							}
						}
						continue
					}
				}
				if !uo.Flags.Get(jsonflags.AllowDuplicateNames) && !seenIdxs.insert(uint(f.id)) {
					// TODO: Unread the object name.
					return newDuplicateNameError(dec.StackPointer(), nil, dec.InputOffset()-len64(val))
				}

				// Process the object member value.
				unmarshal := f.fncs.unmarshal
				if uo.Unmarshalers != nil {
					unmarshal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshal, f.typ)
				}
				flagsOriginal := uo.Flags
				if f.string {
					uo.Flags.Set(jsonflags.StringTag | 1)
				}
				if f.format != "" {
					uo.Flags.Set(jsonflags.FormatTag | 1)
					uo.Format = f.format
				}
				v := addressableValue{va.Field(f.index0), va.forcedAddr} // addressable if struct value is addressable
				if len(f.index) > 0 {
					v = v.fieldByIndex(f.index, true)
					if !v.IsValid() {
						err := newUnmarshalErrorBefore(dec, t, errNilField)
						if !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
							return err
						}
						errUnmarshal = cmp.Or(errUnmarshal, err)
						unmarshal = func(dec *jsontext.Decoder, _ addressableValue, _ *jsonopts.Struct) error {
							return dec.SkipValue()
						}
					}
				}
				err = unmarshal(dec, v, uo)
				uo.Flags = flagsOriginal
				uo.Format = ""
				if err != nil {
					if isFatalError(err, uo.Flags) {
						return err
					}
					errUnmarshal = cmp.Or(errUnmarshal, err)
				}
			}
			if _, err := dec.ReadToken(); err != nil {
				return err
			}
			return errUnmarshal
		}
		return newUnmarshalErrorAfterWithSkipping(dec, t, nil)
	}
	return &fncs
}

func (va addressableValue) fieldByIndex(index []int, mayAlloc bool) addressableValue {
	for _, i := range index {
		va = va.indirect(mayAlloc)
		if !va.IsValid() {
			return va
		}
		va = addressableValue{va.Field(i), va.forcedAddr} // addressable if struct value is addressable
	}
	return va
}

func (va addressableValue) indirect(mayAlloc bool) addressableValue {
	if va.Kind() == reflect.Pointer {
		if va.IsNil() {
			if !mayAlloc || !va.CanSet() {
				return addressableValue{}
			}
			va.Set(reflect.New(va.Type().Elem()))
		}
		va = addressableValue{va.Elem(), false} // dereferenced pointer is always addressable
	}
	return va
}

// isLegacyEmpty reports whether a value is empty according to the v1 definition.
func isLegacyEmpty(v addressableValue) bool {
	// Equivalent to encoding/json.isEmptyValue@v1.21.0.
	switch v.Kind() {
	case reflect.Bool:
		return v.Bool() == false
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.String, reflect.Map, reflect.Slice, reflect.Array:
		return v.Len() == 0
	case reflect.Pointer, reflect.Interface:
		return v.IsNil()
	}
	return false
}

func makeSliceArshaler(t reflect.Type) *arshaler {
	var fncs arshaler
	var (
		once    sync.Once
		valFncs *arshaler
	)
	init := func() {
		valFncs = lookupArshaler(t.Elem())
	}
	fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
		// Check for cycles.
		xe := export.Encoder(enc)
		if xe.Tokens.Depth() > startDetectingCyclesAfter {
			if err := visitPointer(&xe.SeenPointers, va.Value); err != nil {
				return newMarshalErrorBefore(enc, t, err)
			}
			defer leavePointer(&xe.SeenPointers, va.Value)
		}

		emitNull := mo.Flags.Get(jsonflags.FormatNilSliceAsNull)
		if mo.Flags.Has(jsonflags.TagFlags) {
			if mo.Flags.Get(jsonflags.StringTag) && !mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
				return newMarshalErrorBefore(enc, t, errInvalidStringTag)
			}
			if mo.Flags.Has(jsonflags.FormatTag) {
				switch mo.Format {
				case "emitnull":
					emitNull = true
				case "emitempty":
					emitNull = false
				default:
					return newInvalidFormatError(enc, t)
				}
			}
		}

		// Handle empty slices.
		n := va.Len()
		if n == 0 {
			if emitNull && va.IsNil() {
				return enc.WriteToken(jsontext.Null)
			}
			// Optimize for marshaling an empty slice without any preceding whitespace.
			if optimizeCommon && !mo.Flags.Get(jsonflags.AnyWhitespace) && !xe.Tokens.Last.NeedObjectName() {
				xe.Buf = append(xe.Tokens.MayAppendDelim(xe.Buf, '['), "[]"...)
				xe.Tokens.Last.Increment()
				if xe.NeedFlush() {
					return xe.Flush()
				}
				return nil
			}
		}

		once.Do(init)
		if err := enc.WriteToken(jsontext.BeginArray); err != nil {
			return err
		}
		marshal := valFncs.marshal
		if mo.Marshalers != nil {
			marshal, _ = mo.Marshalers.(*Marshalers).lookup(marshal, t.Elem())
		}
		for i := range n {
			v := addressableValue{va.Index(i), false} // indexed slice element is always addressable
			if err := marshal(enc, v, mo); err != nil {
				return err
			}
		}
		if err := enc.WriteToken(jsontext.EndArray); err != nil {
			return err
		}
		return nil
	}
	emptySlice := reflect.MakeSlice(t, 0, 0)
	fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
		if uo.Flags.Has(jsonflags.TagFlags) {
			if uo.Flags.Get(jsonflags.StringTag) && !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
				return newUnmarshalErrorBeforeWithSkipping(dec, t, errInvalidStringTag)
			}
			if uo.Flags.Has(jsonflags.FormatTag) {
				switch uo.Format {
				case "emitnull", "emitempty":
				default:
					return newInvalidFormatError(dec, t)
				}
			}
		}

		tok, err := dec.ReadToken()
		if err != nil {
			return err
		}
		k := tok.Kind()
		switch k {
		case 'n':
			va.SetZero()
			return nil
		case '[':
			once.Do(init)
			unmarshal := valFncs.unmarshal
			if uo.Unmarshalers != nil {
				unmarshal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshal, t.Elem())
			}
			mustZero := true // we do not know the cleanliness of unused capacity
			cap := va.Cap()
			if cap > 0 {
				va.SetLen(cap)
			}
			var i int
			var errUnmarshal error
			for dec.PeekKind() != ']' {
				if i == cap {
					va.Value.Grow(1)
					cap = va.Cap()
					va.SetLen(cap)
					mustZero = false // reflect.Value.Grow ensures new capacity is zero-initialized
				}
				v := addressableValue{va.Index(i), false} // indexed slice element is always addressable
				i++
				if mustZero && !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
					v.SetZero()
				}
				if err := unmarshal(dec, v, uo); err != nil {
					if isFatalError(err, uo.Flags) {
						va.SetLen(i)
						return err
					}
					errUnmarshal = cmp.Or(errUnmarshal, err)
				}
			}
			if i == 0 {
				va.Set(emptySlice)
			} else {
				va.SetLen(i)
			}
			if _, err := dec.ReadToken(); err != nil {
				return err
			}
			return errUnmarshal
		}
		return newUnmarshalErrorAfterWithSkipping(dec, t, nil)
	}
	return &fncs
}

var errArrayUnderflow = errors.New("too few array elements")
var errArrayOverflow = errors.New("too many array elements")

func makeArrayArshaler(t reflect.Type) *arshaler {
	var fncs arshaler
	var (
		once    sync.Once
		valFncs *arshaler
	)
	init := func() {
		valFncs = lookupArshaler(t.Elem())
	}
	n := t.Len()
	fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
		if mo.Flags.Has(jsonflags.TagFlags) {
			if mo.Flags.Get(jsonflags.StringTag) && !mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
				return newMarshalErrorBefore(enc, t, errInvalidStringTag)
			}
			if mo.Flags.Has(jsonflags.FormatTag) {
				return newInvalidFormatError(enc, t)
			}
		}
		once.Do(init)
		if err := enc.WriteToken(jsontext.BeginArray); err != nil {
			return err
		}
		marshal := valFncs.marshal
		if mo.Marshalers != nil {
			marshal, _ = mo.Marshalers.(*Marshalers).lookup(marshal, t.Elem())
		}
		for i := range n {
			v := addressableValue{va.Index(i), va.forcedAddr} // indexed array element is addressable if array is addressable
			if err := marshal(enc, v, mo); err != nil {
				return err
			}
		}
		if err := enc.WriteToken(jsontext.EndArray); err != nil {
			return err
		}
		return nil
	}
	fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
		if uo.Flags.Has(jsonflags.TagFlags) {
			if uo.Flags.Get(jsonflags.StringTag) && !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
				return newUnmarshalErrorBeforeWithSkipping(dec, t, errInvalidStringTag)
			}
			if uo.Flags.Has(jsonflags.FormatTag) {
				return newInvalidFormatError(dec, t)
			}
		}
		tok, err := dec.ReadToken()
		if err != nil {
			return err
		}
		k := tok.Kind()
		switch k {
		case 'n':
			if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
				va.SetZero()
			}
			return nil
		case '[':
			once.Do(init)
			unmarshal := valFncs.unmarshal
			if uo.Unmarshalers != nil {
				unmarshal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshal, t.Elem())
			}
			var i int
			var errUnmarshal error
			for dec.PeekKind() != ']' {
				if i >= n {
					if err := dec.SkipValue(); err != nil {
						return err
					}
					err = errArrayOverflow
					continue
				}
				v := addressableValue{va.Index(i), va.forcedAddr} // indexed array element is addressable if array is addressable
				if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
					v.SetZero()
				}
				if err := unmarshal(dec, v, uo); err != nil {
					if isFatalError(err, uo.Flags) {
						return err
					}
					errUnmarshal = cmp.Or(errUnmarshal, err)
				}
				i++
			}
			for ; i < n; i++ {
				va.Index(i).SetZero()
				err = errArrayUnderflow
			}
			if _, err := dec.ReadToken(); err != nil {
				return err
			}
			if err != nil && !uo.Flags.Get(jsonflags.UnmarshalArrayFromAnyLength) {
				return newUnmarshalErrorAfter(dec, t, err)
			}
			return errUnmarshal
		}
		return newUnmarshalErrorAfterWithSkipping(dec, t, nil)
	}
	return &fncs
}

func makePointerArshaler(t reflect.Type) *arshaler {
	var fncs arshaler
	var (
		once    sync.Once
		valFncs *arshaler
	)
	init := func() {
		valFncs = lookupArshaler(t.Elem())
	}
	fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
		// Check for cycles.
		xe := export.Encoder(enc)
		if xe.Tokens.Depth() > startDetectingCyclesAfter {
			if err := visitPointer(&xe.SeenPointers, va.Value); err != nil {
				return newMarshalErrorBefore(enc, t, err)
			}
			defer leavePointer(&xe.SeenPointers, va.Value)
		}

		// NOTE: Struct.Format is forwarded to underlying marshal.
		if mo.Flags.Get(jsonflags.StringTag) && mo.Flags.Get(jsonflags.StringifyWithLegacySemantics) && t.Elem().Kind() == reflect.Pointer {
			if !mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
				return newMarshalErrorBefore(enc, t, errInvalidStringTag)
			}
			mo.Flags.Clear(jsonflags.StringTag) // the `string` tag option does not apply to nested pointers
		}
		if va.IsNil() {
			return enc.WriteToken(jsontext.Null)
		}
		once.Do(init)
		marshal := valFncs.marshal
		if mo.Marshalers != nil {
			marshal, _ = mo.Marshalers.(*Marshalers).lookup(marshal, t.Elem())
		}
		v := addressableValue{va.Elem(), false} // dereferenced pointer is always addressable
		return marshal(enc, v, mo)
	}
	fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
		// NOTE: Struct.Format is forwarded to underlying unmarshal.
		if dec.PeekKind() == 'n' {
			if _, err := dec.ReadToken(); err != nil {
				return err
			}
			va.SetZero()
			return nil
		}
		if uo.Flags.Get(jsonflags.StringTag) && uo.Flags.Get(jsonflags.StringifyWithLegacySemantics) && t.Elem().Kind() == reflect.Pointer {
			if !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
				return newUnmarshalErrorBeforeWithSkipping(dec, t, errInvalidStringTag)
			}
			uo.Flags.Clear(jsonflags.StringTag) // the `string` tag option does not apply to nested pointers
		}
		once.Do(init)
		unmarshal := valFncs.unmarshal
		if uo.Unmarshalers != nil {
			unmarshal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshal, t.Elem())
		}
		if va.IsNil() {
			va.Set(reflect.New(t.Elem()))
		}
		v := addressableValue{va.Elem(), false} // dereferenced pointer is always addressable
		if err := unmarshal(dec, v, uo); err != nil {
			return err
		}
		if uo.Flags.Get(jsonflags.StringTag) && uo.Flags.Get(jsonflags.StringifyWithLegacySemantics) {
			// A JSON null quoted within a JSON string should take effect
			// within the pointer value, rather than the indirect value.
			//
			// TODO: This does not correctly handle escaped nulls
			// (e.g., "\u006e\u0075\u006c\u006c"), but is good enough
			// for such an esoteric use case of the `string` option.
			if string(export.Decoder(dec).PreviousTokenOrValue()) == `"null"` {
				va.SetZero()
			}
		}
		return nil
	}
	return &fncs
}

func makeInterfaceArshaler(t reflect.Type) *arshaler {
	// NOTE: Values retrieved from an interface are not addressable,
	// so we shallow copy the values to make them addressable and
	// store them back into the interface afterwards.

	var fncs arshaler
	var whichMarshaler reflect.Type
	for _, iface := range allMarshalerTypes {
		if t.Implements(iface) {
			whichMarshaler = t
			break
		}
	}
	fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
		if mo.Flags.Has(jsonflags.TagFlags) {
			if mo.Flags.Get(jsonflags.StringTag) {
				if !mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return newMarshalErrorBefore(enc, t, errInvalidStringTag)
				}
				if mo.Flags.Get(jsonflags.StringifyWithLegacySemantics) {
					mo.Flags.Clear(jsonflags.StringTag) // the `string` tag option does not apply to interface types
				}
			}
			if mo.Flags.Has(jsonflags.FormatTag) {
				return newInvalidFormatError(enc, t)
			}
		}
		if va.IsNil() {
			return enc.WriteToken(jsontext.Null)
		} else if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) && whichMarshaler != nil {
			// The marshaler for a pointer never calls the method on a nil receiver.
			// Wrap the nil pointer within a struct type so that marshal
			// instead appears on a value receiver and may be called.
			if va.Elem().Kind() == reflect.Pointer && va.Elem().IsNil() {
				v2 := newAddressableValue(whichMarshaler)
				switch whichMarshaler {
				case jsonMarshalerToType:
					v2.Set(reflect.ValueOf(struct{ MarshalerTo }{va.Elem().Interface().(MarshalerTo)}))
				case jsonMarshalerType:
					v2.Set(reflect.ValueOf(struct{ Marshaler }{va.Elem().Interface().(Marshaler)}))
				case textAppenderType:
					v2.Set(reflect.ValueOf(struct{ encoding.TextAppender }{va.Elem().Interface().(encoding.TextAppender)}))
				case textMarshalerType:
					v2.Set(reflect.ValueOf(struct{ encoding.TextMarshaler }{va.Elem().Interface().(encoding.TextMarshaler)}))
				}
				va = v2
			}
		}
		v := newAddressableValue(va.Elem().Type())
		v.Set(va.Elem())
		marshal := lookupArshaler(v.Type()).marshal
		if mo.Marshalers != nil {
			marshal, _ = mo.Marshalers.(*Marshalers).lookup(marshal, v.Type())
		}
		// Optimize for the any type if there are no special options.
		if optimizeCommon &&
			t == anyType && !mo.Flags.Get(jsonflags.StringifyNumbers|jsonflags.TagFlags) &&
			(mo.Marshalers == nil || !mo.Marshalers.(*Marshalers).fromAny) {
			return marshalValueAny(enc, va.Elem().Interface(), mo)
		}
		return marshal(enc, v, mo)
	}
	fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
		if uo.Flags.Has(jsonflags.TagFlags) {
			if uo.Flags.Get(jsonflags.StringTag) {
				if !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return newUnmarshalErrorBeforeWithSkipping(dec, t, errInvalidStringTag)
				}
				if uo.Flags.Get(jsonflags.StringifyWithLegacySemantics) {
					uo.Flags.Clear(jsonflags.StringTag) // the `string` tag option does not apply to interface types
				}
			}
			if uo.Flags.Has(jsonflags.FormatTag) {
				return newInvalidFormatError(dec, t)
			}
		}
		if uo.Flags.Get(jsonflags.MergeWithLegacySemantics) && !va.IsNil() {
			// Legacy merge behavior is difficult to explain.
			// In general, it only merges for non-nil pointer kinds.
			// As a special case, unmarshaling a JSON null into a pointer
			// sets a concrete nil pointer of the underlying type
			// (rather than setting the interface value itself to nil).
			e := va.Elem()
			if e.Kind() == reflect.Pointer && !e.IsNil() {
				if dec.PeekKind() == 'n' && e.Elem().Kind() == reflect.Pointer {
					if _, err := dec.ReadToken(); err != nil {
						return err
					}
					va.Elem().Elem().SetZero()
					return nil
				}
			} else {
				va.SetZero()
			}
		}
		if dec.PeekKind() == 'n' {
			if _, err := dec.ReadToken(); err != nil {
				return err
			}
			va.SetZero()
			return nil
		}
		var v addressableValue
		if va.IsNil() {
			// Optimize for the any type if there are no special options.
			// We do not care about stringified numbers since JSON strings
			// are always unmarshaled into an any value as Go strings.
			// Duplicate name check must be enforced since unmarshalValueAny
			// does not implement merge semantics.
			if optimizeCommon &&
				t == anyType && !uo.Flags.Get(jsonflags.AllowDuplicateNames|jsonflags.FormatTag) &&
				(uo.Unmarshalers == nil || !uo.Unmarshalers.(*Unmarshalers).fromAny) {
				v, err := unmarshalValueAny(dec, uo)
				// We must check for nil interface values up front.
				// See https://go.dev/issue/52310.
				if v != nil {
					va.Set(reflect.ValueOf(v))
				}
				return err
			}

			k := dec.PeekKind()
			if !isAnyType(t) {
				return newUnmarshalErrorBeforeWithSkipping(dec, t, internal.ErrNilInterface)
			}
			switch k {
			case 'f', 't':
				v = newAddressableValue(boolType)
			case '"':
				v = newAddressableValue(stringType)
			case '0':
				if uo.Flags.Get(jsonflags.UnmarshalAnyWithRawNumber) {
					v = addressableValue{reflect.ValueOf(internal.NewRawNumber()).Elem(), true}
				} else {
					v = newAddressableValue(float64Type)
				}
			case '{':
				v = newAddressableValue(mapStringAnyType)
			case '[':
				v = newAddressableValue(sliceAnyType)
			default:
				// If k is invalid (e.g., due to an I/O or syntax error), then
				// that will be cached by PeekKind and returned by ReadValue.
				// If k is '}' or ']', then ReadValue must error since
				// those are invalid kinds at the start of a JSON value.
				_, err := dec.ReadValue()
				return err
			}
		} else {
			// Shallow copy the existing value to keep it addressable.
			// Any mutations at the top-level of the value will be observable
			// since we always store this value back into the interface value.
			v = newAddressableValue(va.Elem().Type())
			v.Set(va.Elem())
		}
		unmarshal := lookupArshaler(v.Type()).unmarshal
		if uo.Unmarshalers != nil {
			unmarshal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshal, v.Type())
		}
		err := unmarshal(dec, v, uo)
		va.Set(v.Value)
		return err
	}
	return &fncs
}

// isAnyType reports whether t is equivalent to the any interface type.
func isAnyType(t reflect.Type) bool {
	// This is forward compatible if the Go language permits type sets within
	// ordinary interfaces where an interface with zero methods does not
	// necessarily mean it can hold every possible Go type.
	// See https://go.dev/issue/45346.
	return t == anyType || anyType.Implements(t)
}

func makeInvalidArshaler(t reflect.Type) *arshaler {
	var fncs arshaler
	fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
		return newMarshalErrorBefore(enc, t, nil)
	}
	fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
		// Under legacy error semantics, unmarshal continues on even with errors.
		// Thus, always consume the value first.
		// As a special-case, null is permitted for unsupported types.
		if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
			switch val, err := dec.ReadValue(); {
			case err != nil:
				return err
			case val.Kind() == 'n':
				return nil
			default:
				return newUnmarshalErrorAfter(dec, t, nil)
			}
		}
		return newUnmarshalErrorBefore(dec, t, nil)
	}
	return &fncs
}

func stringOrNumberKind(isString bool) jsontext.Kind {
	if isString {
		return '"'
	} else {
		return '0'
	}
}

type uintSet64 uint64

func (s uintSet64) has(i uint) bool { return s&(1<<i) > 0 }
func (s *uintSet64) set(i uint)     { *s |= 1 << i }

// uintSet is a set of unsigned integers.
// It is optimized for most integers being close to zero.
type uintSet struct {
	lo uintSet64
	hi []uintSet64
}

// has reports whether i is in the set.
func (s *uintSet) has(i uint) bool {
	if i < 64 {
		return s.lo.has(i)
	} else {
		i -= 64
		iHi, iLo := int(i/64), i%64
		return iHi < len(s.hi) && s.hi[iHi].has(iLo)
	}
}

// insert inserts i into the set and reports whether it was the first insertion.
func (s *uintSet) insert(i uint) bool {
	// TODO: Make this inlinable at least for the lower 64-bit case.
	if i < 64 {
		has := s.lo.has(i)
		s.lo.set(i)
		return !has
	} else {
		i -= 64
		iHi, iLo := int(i/64), i%64
		if iHi >= len(s.hi) {
			s.hi = append(s.hi, make([]uintSet64, iHi+1-len(s.hi))...)
			s.hi = s.hi[:cap(s.hi)]
		}
		has := s.hi[iHi].has(iLo)
		s.hi[iHi].set(iLo)
		return !has
	}
}
