// 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 {
					var numMatch int
					for _, f2 := range fields.lookupByFoldedName(name) {
						if f2.matchFoldedName(name, &uo.Flags) {
							if f == nil {
								f = f2 // use first seen name by breadth-first order
							}
							numMatch++
						}
					}
					if numMatch > 1 && !uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
						return newUnmarshalErrorAfter(dec, t, errAmbiguousName)
					}
					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
	}
}
