encode.go

   1// Vendored from Go 1.24.0-pre-release
   2// To find alterations, check package shims, and comments beginning in SHIM().
   3//
   4// Copyright 2010 The Go Authors. All rights reserved.
   5// Use of this source code is governed by a BSD-style
   6// license that can be found in the LICENSE file.
   7
   8// Package json implements encoding and decoding of JSON as defined in
   9// RFC 7159. The mapping between JSON and Go values is described
  10// in the documentation for the Marshal and Unmarshal functions.
  11//
  12// See "JSON and Go" for an introduction to this package:
  13// https://golang.org/doc/articles/json_and_go.html
  14package json
  15
  16import (
  17	"bytes"
  18	"cmp"
  19	"encoding"
  20	"encoding/base64"
  21	"fmt"
  22	"github.com/anthropics/anthropic-sdk-go/internal/encoding/json/sentinel"
  23	"github.com/anthropics/anthropic-sdk-go/internal/encoding/json/shims"
  24	"math"
  25	"reflect"
  26	"slices"
  27	"strconv"
  28	"strings"
  29	"sync"
  30	"unicode"
  31	"unicode/utf8"
  32	_ "unsafe" // for linkname
  33)
  34
  35// Marshal returns the JSON encoding of v.
  36//
  37// Marshal traverses the value v recursively.
  38// If an encountered value implements [Marshaler]
  39// and is not a nil pointer, Marshal calls [Marshaler.MarshalJSON]
  40// to produce JSON. If no [Marshaler.MarshalJSON] method is present but the
  41// value implements [encoding.TextMarshaler] instead, Marshal calls
  42// [encoding.TextMarshaler.MarshalText] and encodes the result as a JSON string.
  43// The nil pointer exception is not strictly necessary
  44// but mimics a similar, necessary exception in the behavior of
  45// [Unmarshaler.UnmarshalJSON].
  46//
  47// Otherwise, Marshal uses the following type-dependent default encodings:
  48//
  49// Boolean values encode as JSON booleans.
  50//
  51// Floating point, integer, and [Number] values encode as JSON numbers.
  52// NaN and +/-Inf values will return an [UnsupportedValueError].
  53//
  54// String values encode as JSON strings coerced to valid UTF-8,
  55// replacing invalid bytes with the Unicode replacement rune.
  56// So that the JSON will be safe to embed inside HTML <script> tags,
  57// the string is encoded using [HTMLEscape],
  58// which replaces "<", ">", "&", U+2028, and U+2029 are escaped
  59// to "\u003c","\u003e", "\u0026", "\u2028", and "\u2029".
  60// This replacement can be disabled when using an [Encoder],
  61// by calling [Encoder.SetEscapeHTML](false).
  62//
  63// Array and slice values encode as JSON arrays, except that
  64// []byte encodes as a base64-encoded string, and a nil slice
  65// encodes as the null JSON value.
  66//
  67// Struct values encode as JSON objects.
  68// Each exported struct field becomes a member of the object, using the
  69// field name as the object key, unless the field is omitted for one of the
  70// reasons given below.
  71//
  72// The encoding of each struct field can be customized by the format string
  73// stored under the "json" key in the struct field's tag.
  74// The format string gives the name of the field, possibly followed by a
  75// comma-separated list of options. The name may be empty in order to
  76// specify options without overriding the default field name.
  77//
  78// The "omitempty" option specifies that the field should be omitted
  79// from the encoding if the field has an empty value, defined as
  80// false, 0, a nil pointer, a nil interface value, and any array,
  81// slice, map, or string of length zero.
  82//
  83// As a special case, if the field tag is "-", the field is always omitted.
  84// Note that a field with name "-" can still be generated using the tag "-,".
  85//
  86// Examples of struct field tags and their meanings:
  87//
  88//	// Field appears in JSON as key "myName".
  89//	Field int `json:"myName"`
  90//
  91//	// Field appears in JSON as key "myName" and
  92//	// the field is omitted from the object if its value is empty,
  93//	// as defined above.
  94//	Field int `json:"myName,omitempty"`
  95//
  96//	// Field appears in JSON as key "Field" (the default), but
  97//	// the field is skipped if empty.
  98//	// Note the leading comma.
  99//	Field int `json:",omitempty"`
 100//
 101//	// Field is ignored by this package.
 102//	Field int `json:"-"`
 103//
 104//	// Field appears in JSON as key "-".
 105//	Field int `json:"-,"`
 106//
 107// The "omitzero" option specifies that the field should be omitted
 108// from the encoding if the field has a zero value, according to rules:
 109//
 110// 1) If the field type has an "IsZero() bool" method, that will be used to
 111// determine whether the value is zero.
 112//
 113// 2) Otherwise, the value is zero if it is the zero value for its type.
 114//
 115// If both "omitempty" and "omitzero" are specified, the field will be omitted
 116// if the value is either empty or zero (or both).
 117//
 118// The "string" option signals that a field is stored as JSON inside a
 119// JSON-encoded string. It applies only to fields of string, floating point,
 120// integer, or boolean types. This extra level of encoding is sometimes used
 121// when communicating with JavaScript programs:
 122//
 123//	Int64String int64 `json:",string"`
 124//
 125// The key name will be used if it's a non-empty string consisting of
 126// only Unicode letters, digits, and ASCII punctuation except quotation
 127// marks, backslash, and comma.
 128//
 129// Embedded struct fields are usually marshaled as if their inner exported fields
 130// were fields in the outer struct, subject to the usual Go visibility rules amended
 131// as described in the next paragraph.
 132// An anonymous struct field with a name given in its JSON tag is treated as
 133// having that name, rather than being anonymous.
 134// An anonymous struct field of interface type is treated the same as having
 135// that type as its name, rather than being anonymous.
 136//
 137// The Go visibility rules for struct fields are amended for JSON when
 138// deciding which field to marshal or unmarshal. If there are
 139// multiple fields at the same level, and that level is the least
 140// nested (and would therefore be the nesting level selected by the
 141// usual Go rules), the following extra rules apply:
 142//
 143// 1) Of those fields, if any are JSON-tagged, only tagged fields are considered,
 144// even if there are multiple untagged fields that would otherwise conflict.
 145//
 146// 2) If there is exactly one field (tagged or not according to the first rule), that is selected.
 147//
 148// 3) Otherwise there are multiple fields, and all are ignored; no error occurs.
 149//
 150// Handling of anonymous struct fields is new in Go 1.1.
 151// Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of
 152// an anonymous struct field in both current and earlier versions, give the field
 153// a JSON tag of "-".
 154//
 155// Map values encode as JSON objects. The map's key type must either be a
 156// string, an integer type, or implement [encoding.TextMarshaler]. The map keys
 157// are sorted and used as JSON object keys by applying the following rules,
 158// subject to the UTF-8 coercion described for string values above:
 159//   - keys of any string type are used directly
 160//   - keys that implement [encoding.TextMarshaler] are marshaled
 161//   - integer keys are converted to strings
 162//
 163// Pointer values encode as the value pointed to.
 164// A nil pointer encodes as the null JSON value.
 165//
 166// Interface values encode as the value contained in the interface.
 167// A nil interface value encodes as the null JSON value.
 168//
 169// Channel, complex, and function values cannot be encoded in JSON.
 170// Attempting to encode such a value causes Marshal to return
 171// an [UnsupportedTypeError].
 172//
 173// JSON cannot represent cyclic data structures and Marshal does not
 174// handle them. Passing cyclic structures to Marshal will result in
 175// an error.
 176func Marshal(v any) ([]byte, error) {
 177	e := newEncodeState()
 178	defer encodeStatePool.Put(e)
 179
 180	err := e.marshal(v, encOpts{escapeHTML: true})
 181	if err != nil {
 182		return nil, err
 183	}
 184	buf := append([]byte(nil), e.Bytes()...)
 185
 186	return buf, nil
 187}
 188
 189// MarshalIndent is like [Marshal] but applies [Indent] to format the output.
 190// Each JSON element in the output will begin on a new line beginning with prefix
 191// followed by one or more copies of indent according to the indentation nesting.
 192func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
 193	b, err := Marshal(v)
 194	if err != nil {
 195		return nil, err
 196	}
 197	b2 := make([]byte, 0, indentGrowthFactor*len(b))
 198	b2, err = appendIndent(b2, b, prefix, indent)
 199	if err != nil {
 200		return nil, err
 201	}
 202	return b2, nil
 203}
 204
 205// Marshaler is the interface implemented by types that
 206// can marshal themselves into valid JSON.
 207type Marshaler interface {
 208	MarshalJSON() ([]byte, error)
 209}
 210
 211// An UnsupportedTypeError is returned by [Marshal] when attempting
 212// to encode an unsupported value type.
 213type UnsupportedTypeError struct {
 214	Type reflect.Type
 215}
 216
 217func (e *UnsupportedTypeError) Error() string {
 218	return "json: unsupported type: " + e.Type.String()
 219}
 220
 221// An UnsupportedValueError is returned by [Marshal] when attempting
 222// to encode an unsupported value.
 223type UnsupportedValueError struct {
 224	Value reflect.Value
 225	Str   string
 226}
 227
 228func (e *UnsupportedValueError) Error() string {
 229	return "json: unsupported value: " + e.Str
 230}
 231
 232// Before Go 1.2, an InvalidUTF8Error was returned by [Marshal] when
 233// attempting to encode a string value with invalid UTF-8 sequences.
 234// As of Go 1.2, [Marshal] instead coerces the string to valid UTF-8 by
 235// replacing invalid bytes with the Unicode replacement rune U+FFFD.
 236//
 237// Deprecated: No longer used; kept for compatibility.
 238type InvalidUTF8Error struct {
 239	S string // the whole string value that caused the error
 240}
 241
 242func (e *InvalidUTF8Error) Error() string {
 243	return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
 244}
 245
 246// A MarshalerError represents an error from calling a
 247// [Marshaler.MarshalJSON] or [encoding.TextMarshaler.MarshalText] method.
 248type MarshalerError struct {
 249	Type       reflect.Type
 250	Err        error
 251	sourceFunc string
 252}
 253
 254func (e *MarshalerError) Error() string {
 255	srcFunc := e.sourceFunc
 256	if srcFunc == "" {
 257		srcFunc = "MarshalJSON"
 258	}
 259	return "json: error calling " + srcFunc +
 260		" for type " + e.Type.String() +
 261		": " + e.Err.Error()
 262}
 263
 264// Unwrap returns the underlying error.
 265func (e *MarshalerError) Unwrap() error { return e.Err }
 266
 267const hex = "0123456789abcdef"
 268
 269// An encodeState encodes JSON into a bytes.Buffer.
 270type encodeState struct {
 271	bytes.Buffer // accumulated output
 272
 273	// Keep track of what pointers we've seen in the current recursive call
 274	// path, to avoid cycles that could lead to a stack overflow. Only do
 275	// the relatively expensive map operations if ptrLevel is larger than
 276	// startDetectingCyclesAfter, so that we skip the work if we're within a
 277	// reasonable amount of nested pointers deep.
 278	ptrLevel uint
 279	ptrSeen  map[any]struct{}
 280}
 281
 282const startDetectingCyclesAfter = 1000
 283
 284var encodeStatePool sync.Pool
 285
 286func newEncodeState() *encodeState {
 287	if v := encodeStatePool.Get(); v != nil {
 288		e := v.(*encodeState)
 289		e.Reset()
 290		if len(e.ptrSeen) > 0 {
 291			panic("ptrEncoder.encode should have emptied ptrSeen via defers")
 292		}
 293		e.ptrLevel = 0
 294		return e
 295	}
 296	return &encodeState{ptrSeen: make(map[any]struct{})}
 297}
 298
 299// jsonError is an error wrapper type for internal use only.
 300// Panics with errors are wrapped in jsonError so that the top-level recover
 301// can distinguish intentional panics from this package.
 302type jsonError struct{ error }
 303
 304func (e *encodeState) marshal(v any, opts encOpts) (err error) {
 305	defer func() {
 306		if r := recover(); r != nil {
 307			if je, ok := r.(jsonError); ok {
 308				err = je.error
 309			} else {
 310				panic(r)
 311			}
 312		}
 313	}()
 314	e.reflectValue(reflect.ValueOf(v), opts)
 315	return nil
 316}
 317
 318// error aborts the encoding by panicking with err wrapped in jsonError.
 319func (e *encodeState) error(err error) {
 320	panic(jsonError{err})
 321}
 322
 323func isEmptyValue(v reflect.Value) bool {
 324	switch v.Kind() {
 325	case reflect.String:
 326		return v.Len() == 0
 327	case reflect.Array, reflect.Map, reflect.Slice:
 328		return v.Len() == 0
 329	case reflect.Bool,
 330		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
 331		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
 332		reflect.Float32, reflect.Float64,
 333		reflect.Interface, reflect.Pointer:
 334		return v.IsZero()
 335	}
 336	return false
 337}
 338
 339func (e *encodeState) reflectValue(v reflect.Value, opts encOpts) {
 340	valueEncoder(v)(e, v, opts)
 341}
 342
 343type encOpts struct {
 344	// quoted causes primitive fields to be encoded inside JSON strings.
 345	quoted bool
 346	// escapeHTML causes '<', '>', and '&' to be escaped in JSON strings.
 347	escapeHTML bool
 348	// EDIT(begin): save the timefmt
 349	timefmt string
 350	// EDIT(end)
 351}
 352
 353type encoderFunc func(e *encodeState, v reflect.Value, opts encOpts)
 354
 355var encoderCache sync.Map // map[reflect.Type]encoderFunc
 356
 357func valueEncoder(v reflect.Value) encoderFunc {
 358	if !v.IsValid() {
 359		return invalidValueEncoder
 360	}
 361	return typeEncoder(v.Type())
 362}
 363
 364func typeEncoder(t reflect.Type) encoderFunc {
 365	if fi, ok := encoderCache.Load(t); ok {
 366		return fi.(encoderFunc)
 367	}
 368
 369	// To deal with recursive types, populate the map with an
 370	// indirect func before we build it. This type waits on the
 371	// real func (f) to be ready and then calls it. This indirect
 372	// func is only used for recursive types.
 373	var (
 374		wg sync.WaitGroup
 375		f  encoderFunc
 376	)
 377	wg.Add(1)
 378	fi, loaded := encoderCache.LoadOrStore(t, encoderFunc(func(e *encodeState, v reflect.Value, opts encOpts) {
 379		wg.Wait()
 380		f(e, v, opts)
 381	}))
 382	if loaded {
 383		return fi.(encoderFunc)
 384	}
 385
 386	// Compute the real encoder and replace the indirect func with it.
 387	f = newTypeEncoder(t, true)
 388	wg.Done()
 389	encoderCache.Store(t, f)
 390	return f
 391}
 392
 393var (
 394	// SHIM(begin): TypeFor[T]() reflect.Type
 395	marshalerType     = shims.TypeFor[Marshaler]()
 396	textMarshalerType = shims.TypeFor[encoding.TextMarshaler]()
 397	// SHIM(end)
 398)
 399
 400// newTypeEncoder constructs an encoderFunc for a type.
 401// The returned encoder only checks CanAddr when allowAddr is true.
 402func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
 403	// EDIT(begin): add custom time encoder
 404	if t == timeType {
 405		return newTimeEncoder()
 406	}
 407	// EDIT(end)
 408
 409	// If we have a non-pointer value whose type implements
 410	// Marshaler with a value receiver, then we're better off taking
 411	// the address of the value - otherwise we end up with an
 412	// allocation as we cast the value to an interface.
 413	if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(marshalerType) {
 414		return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false))
 415	}
 416
 417	if t.Implements(marshalerType) {
 418		return marshalerEncoder
 419	}
 420	if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(textMarshalerType) {
 421		return newCondAddrEncoder(addrTextMarshalerEncoder, newTypeEncoder(t, false))
 422	}
 423	if t.Implements(textMarshalerType) {
 424		return textMarshalerEncoder
 425	}
 426
 427	switch t.Kind() {
 428	case reflect.Bool:
 429		return boolEncoder
 430	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 431		return intEncoder
 432	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 433		return uintEncoder
 434	case reflect.Float32:
 435		return float32Encoder
 436	case reflect.Float64:
 437		return float64Encoder
 438	case reflect.String:
 439		return stringEncoder
 440	case reflect.Interface:
 441		return interfaceEncoder
 442	case reflect.Struct:
 443		return newStructEncoder(t)
 444	case reflect.Map:
 445		return newMapEncoder(t)
 446	case reflect.Slice:
 447		return newSliceEncoder(t)
 448	case reflect.Array:
 449		return newArrayEncoder(t)
 450	case reflect.Pointer:
 451		return newPtrEncoder(t)
 452	default:
 453		return unsupportedTypeEncoder
 454	}
 455}
 456
 457func invalidValueEncoder(e *encodeState, v reflect.Value, _ encOpts) {
 458	e.WriteString("null")
 459}
 460
 461func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
 462	if v.Kind() == reflect.Pointer && v.IsNil() {
 463		e.WriteString("null")
 464		return
 465	}
 466	m, ok := v.Interface().(Marshaler)
 467	if !ok {
 468		e.WriteString("null")
 469		return
 470	}
 471
 472	// EDIT(begin): use custom time encoder
 473	if timeMarshalEncoder(e, v, opts) {
 474		return
 475	}
 476	// EDIT(end)
 477
 478	b, err := m.MarshalJSON()
 479	if err == nil {
 480		e.Grow(len(b))
 481		out := e.AvailableBuffer()
 482		out, err = appendCompact(out, b, opts.escapeHTML)
 483		e.Buffer.Write(out)
 484	}
 485	if err != nil {
 486		e.error(&MarshalerError{v.Type(), err, "MarshalJSON"})
 487	}
 488}
 489
 490func addrMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
 491	va := v.Addr()
 492	if va.IsNil() {
 493		e.WriteString("null")
 494		return
 495	}
 496
 497	// EDIT(begin): use custom time encoder
 498	if timeMarshalEncoder(e, v, opts) {
 499		return
 500	}
 501	// EDIT(end)
 502
 503	m := va.Interface().(Marshaler)
 504	b, err := m.MarshalJSON()
 505	if err == nil {
 506		e.Grow(len(b))
 507		out := e.AvailableBuffer()
 508		out, err = appendCompact(out, b, opts.escapeHTML)
 509		e.Buffer.Write(out)
 510	}
 511	if err != nil {
 512		e.error(&MarshalerError{v.Type(), err, "MarshalJSON"})
 513	}
 514}
 515
 516func textMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
 517	if v.Kind() == reflect.Pointer && v.IsNil() {
 518		e.WriteString("null")
 519		return
 520	}
 521	m, ok := v.Interface().(encoding.TextMarshaler)
 522	if !ok {
 523		e.WriteString("null")
 524		return
 525	}
 526	b, err := m.MarshalText()
 527	if err != nil {
 528		e.error(&MarshalerError{v.Type(), err, "MarshalText"})
 529	}
 530	e.Write(appendString(e.AvailableBuffer(), b, opts.escapeHTML))
 531}
 532
 533func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
 534	va := v.Addr()
 535	if va.IsNil() {
 536		e.WriteString("null")
 537		return
 538	}
 539	m := va.Interface().(encoding.TextMarshaler)
 540	b, err := m.MarshalText()
 541	if err != nil {
 542		e.error(&MarshalerError{v.Type(), err, "MarshalText"})
 543	}
 544	e.Write(appendString(e.AvailableBuffer(), b, opts.escapeHTML))
 545}
 546
 547func boolEncoder(e *encodeState, v reflect.Value, opts encOpts) {
 548	b := e.AvailableBuffer()
 549	b = mayAppendQuote(b, opts.quoted)
 550	b = strconv.AppendBool(b, v.Bool())
 551	b = mayAppendQuote(b, opts.quoted)
 552	e.Write(b)
 553}
 554
 555func intEncoder(e *encodeState, v reflect.Value, opts encOpts) {
 556	b := e.AvailableBuffer()
 557	b = mayAppendQuote(b, opts.quoted)
 558	b = strconv.AppendInt(b, v.Int(), 10)
 559	b = mayAppendQuote(b, opts.quoted)
 560	e.Write(b)
 561}
 562
 563func uintEncoder(e *encodeState, v reflect.Value, opts encOpts) {
 564	b := e.AvailableBuffer()
 565	b = mayAppendQuote(b, opts.quoted)
 566	b = strconv.AppendUint(b, v.Uint(), 10)
 567	b = mayAppendQuote(b, opts.quoted)
 568	e.Write(b)
 569}
 570
 571type floatEncoder int // number of bits
 572
 573func (bits floatEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
 574	f := v.Float()
 575	if math.IsInf(f, 0) || math.IsNaN(f) {
 576		e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, int(bits))})
 577	}
 578
 579	// Convert as if by ES6 number to string conversion.
 580	// This matches most other JSON generators.
 581	// See golang.org/issue/6384 and golang.org/issue/14135.
 582	// Like fmt %g, but the exponent cutoffs are different
 583	// and exponents themselves are not padded to two digits.
 584	b := e.AvailableBuffer()
 585	b = mayAppendQuote(b, opts.quoted)
 586	abs := math.Abs(f)
 587	fmt := byte('f')
 588	// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
 589	if abs != 0 {
 590		if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
 591			fmt = 'e'
 592		}
 593	}
 594	b = strconv.AppendFloat(b, f, fmt, -1, int(bits))
 595	if fmt == 'e' {
 596		// clean up e-09 to e-9
 597		n := len(b)
 598		if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' {
 599			b[n-2] = b[n-1]
 600			b = b[:n-1]
 601		}
 602	}
 603	b = mayAppendQuote(b, opts.quoted)
 604	e.Write(b)
 605}
 606
 607var (
 608	float32Encoder = (floatEncoder(32)).encode
 609	float64Encoder = (floatEncoder(64)).encode
 610)
 611
 612func stringEncoder(e *encodeState, v reflect.Value, opts encOpts) {
 613	if v.Type() == numberType {
 614		numStr := v.String()
 615		// In Go1.5 the empty string encodes to "0", while this is not a valid number literal
 616		// we keep compatibility so check validity after this.
 617		if numStr == "" {
 618			numStr = "0" // Number's zero-val
 619		}
 620		if !isValidNumber(numStr) {
 621			e.error(fmt.Errorf("json: invalid number literal %q", numStr))
 622		}
 623		b := e.AvailableBuffer()
 624		b = mayAppendQuote(b, opts.quoted)
 625		b = append(b, numStr...)
 626		b = mayAppendQuote(b, opts.quoted)
 627		e.Write(b)
 628		return
 629	}
 630	if opts.quoted {
 631		b := appendString(nil, v.String(), opts.escapeHTML)
 632		e.Write(appendString(e.AvailableBuffer(), b, false)) // no need to escape again since it is already escaped
 633	} else {
 634		e.Write(appendString(e.AvailableBuffer(), v.String(), opts.escapeHTML))
 635	}
 636}
 637
 638// isValidNumber reports whether s is a valid JSON number literal.
 639//
 640// isValidNumber should be an internal detail,
 641// but widely used packages access it using linkname.
 642// Notable members of the hall of shame include:
 643//   - github.com/bytedance/sonic
 644//
 645// Do not remove or change the type signature.
 646// See go.dev/issue/67401.
 647//
 648//go:linkname isValidNumber
 649func isValidNumber(s string) bool {
 650	// This function implements the JSON numbers grammar.
 651	// See https://tools.ietf.org/html/rfc7159#section-6
 652	// and https://www.json.org/img/number.png
 653
 654	if s == "" {
 655		return false
 656	}
 657
 658	// Optional -
 659	if s[0] == '-' {
 660		s = s[1:]
 661		if s == "" {
 662			return false
 663		}
 664	}
 665
 666	// Digits
 667	switch {
 668	default:
 669		return false
 670
 671	case s[0] == '0':
 672		s = s[1:]
 673
 674	case '1' <= s[0] && s[0] <= '9':
 675		s = s[1:]
 676		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
 677			s = s[1:]
 678		}
 679	}
 680
 681	// . followed by 1 or more digits.
 682	if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
 683		s = s[2:]
 684		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
 685			s = s[1:]
 686		}
 687	}
 688
 689	// e or E followed by an optional - or + and
 690	// 1 or more digits.
 691	if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
 692		s = s[1:]
 693		if s[0] == '+' || s[0] == '-' {
 694			s = s[1:]
 695			if s == "" {
 696				return false
 697			}
 698		}
 699		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
 700			s = s[1:]
 701		}
 702	}
 703
 704	// Make sure we are at the end.
 705	return s == ""
 706}
 707
 708func interfaceEncoder(e *encodeState, v reflect.Value, opts encOpts) {
 709	if v.IsNil() {
 710		e.WriteString("null")
 711		return
 712	}
 713	e.reflectValue(v.Elem(), opts)
 714}
 715
 716func unsupportedTypeEncoder(e *encodeState, v reflect.Value, _ encOpts) {
 717	e.error(&UnsupportedTypeError{v.Type()})
 718}
 719
 720type structEncoder struct {
 721	fields structFields
 722}
 723
 724type structFields struct {
 725	list         []field
 726	byExactName  map[string]*field
 727	byFoldedName map[string]*field
 728}
 729
 730func (se structEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
 731	next := byte('{')
 732FieldLoop:
 733	for i := range se.fields.list {
 734		f := &se.fields.list[i]
 735
 736		// Find the nested struct field by following f.index.
 737		fv := v
 738		for _, i := range f.index {
 739			if fv.Kind() == reflect.Pointer {
 740				if fv.IsNil() {
 741					continue FieldLoop
 742				}
 743				fv = fv.Elem()
 744			}
 745			fv = fv.Field(i)
 746		}
 747
 748		if (f.omitEmpty && isEmptyValue(fv)) ||
 749			(f.omitZero && (f.isZero == nil && fv.IsZero() || (f.isZero != nil && f.isZero(fv)))) {
 750			continue
 751		}
 752		e.WriteByte(next)
 753		next = ','
 754		if opts.escapeHTML {
 755			e.WriteString(f.nameEscHTML)
 756		} else {
 757			e.WriteString(f.nameNonEsc)
 758		}
 759		opts.quoted = f.quoted
 760		f.encoder(e, fv, opts)
 761	}
 762	if next == '{' {
 763		e.WriteString("{}")
 764	} else {
 765		e.WriteByte('}')
 766	}
 767}
 768
 769func newStructEncoder(t reflect.Type) encoderFunc {
 770	se := structEncoder{fields: cachedTypeFields(t)}
 771	return se.encode
 772}
 773
 774type mapEncoder struct {
 775	elemEnc encoderFunc
 776}
 777
 778func (me mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
 779	if v.IsNil() {
 780		e.WriteString("null")
 781		return
 782	}
 783	if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
 784		// We're a large number of nested ptrEncoder.encode calls deep;
 785		// start checking if we've run into a pointer cycle.
 786		ptr := v.UnsafePointer()
 787		if _, ok := e.ptrSeen[ptr]; ok {
 788			e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
 789		}
 790		e.ptrSeen[ptr] = struct{}{}
 791		defer delete(e.ptrSeen, ptr)
 792	}
 793	e.WriteByte('{')
 794
 795	// Extract and sort the keys.
 796	var (
 797		sv  = make([]reflectWithString, v.Len())
 798		mi  = v.MapRange()
 799		err error
 800	)
 801	for i := 0; mi.Next(); i++ {
 802		if sv[i].ks, err = resolveKeyName(mi.Key()); err != nil {
 803			e.error(fmt.Errorf("json: encoding error for type %q: %q", v.Type().String(), err.Error()))
 804		}
 805		sv[i].v = mi.Value()
 806	}
 807	slices.SortFunc(sv, func(i, j reflectWithString) int {
 808		return strings.Compare(i.ks, j.ks)
 809	})
 810
 811	for i, kv := range sv {
 812		if i > 0 {
 813			e.WriteByte(',')
 814		}
 815		e.Write(appendString(e.AvailableBuffer(), kv.ks, opts.escapeHTML))
 816		e.WriteByte(':')
 817		me.elemEnc(e, kv.v, opts)
 818	}
 819	e.WriteByte('}')
 820	e.ptrLevel--
 821}
 822
 823func newMapEncoder(t reflect.Type) encoderFunc {
 824	switch t.Key().Kind() {
 825	case reflect.String,
 826		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
 827		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 828	default:
 829		if !t.Key().Implements(textMarshalerType) {
 830			return unsupportedTypeEncoder
 831		}
 832	}
 833	me := mapEncoder{typeEncoder(t.Elem())}
 834	return me.encode
 835}
 836
 837func encodeByteSlice(e *encodeState, v reflect.Value, _ encOpts) {
 838	if v.IsNil() {
 839		e.WriteString("null")
 840		return
 841	}
 842
 843	s := v.Bytes()
 844	b := e.AvailableBuffer()
 845	b = append(b, '"')
 846	// SHIM(base64): base64.StdEncoding.AppendEncode([]byte, []byte) []byte
 847	b = (shims.AppendableStdEncoding{Encoding: base64.StdEncoding}).AppendEncode(b, s)
 848	b = append(b, '"')
 849	e.Write(b)
 850}
 851
 852// sliceEncoder just wraps an arrayEncoder, checking to make sure the value isn't nil.
 853type sliceEncoder struct {
 854	arrayEnc encoderFunc
 855}
 856
 857func (se sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
 858	if v.IsNil() {
 859		e.WriteString("null")
 860		return
 861	}
 862	if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
 863		// We're a large number of nested ptrEncoder.encode calls deep;
 864		// start checking if we've run into a pointer cycle.
 865		// Here we use a struct to memorize the pointer to the first element of the slice
 866		// and its length.
 867		ptr := struct {
 868			ptr any // always an unsafe.Pointer, but avoids a dependency on package unsafe
 869			len int
 870		}{v.UnsafePointer(), v.Len()}
 871		if _, ok := e.ptrSeen[ptr]; ok {
 872			e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
 873		}
 874		e.ptrSeen[ptr] = struct{}{}
 875		defer delete(e.ptrSeen, ptr)
 876	}
 877	se.arrayEnc(e, v, opts)
 878	e.ptrLevel--
 879}
 880
 881func newSliceEncoder(t reflect.Type) encoderFunc {
 882	// Byte slices get special treatment; arrays don't.
 883	if t.Elem().Kind() == reflect.Uint8 {
 884		p := reflect.PointerTo(t.Elem())
 885		if !p.Implements(marshalerType) && !p.Implements(textMarshalerType) {
 886			return encodeByteSlice
 887		}
 888	}
 889	enc := sliceEncoder{newArrayEncoder(t)}
 890	return enc.encode
 891}
 892
 893type arrayEncoder struct {
 894	elemEnc encoderFunc
 895}
 896
 897func (ae arrayEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
 898	e.WriteByte('[')
 899	n := v.Len()
 900	for i := 0; i < n; i++ {
 901		if i > 0 {
 902			e.WriteByte(',')
 903		}
 904		ae.elemEnc(e, v.Index(i), opts)
 905	}
 906	e.WriteByte(']')
 907}
 908
 909func newArrayEncoder(t reflect.Type) encoderFunc {
 910	enc := arrayEncoder{typeEncoder(t.Elem())}
 911	return enc.encode
 912}
 913
 914type ptrEncoder struct {
 915	elemEnc encoderFunc
 916}
 917
 918func (pe ptrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
 919	// EDIT(begin)
 920	//
 921	// if v.IsNil()  {
 922	// 	e.WriteString("null")
 923	// 	return
 924	// }
 925
 926	if v.IsNil() || sentinel.IsValueNullPtr(v) || sentinel.IsValueNullSlice(v) {
 927		e.WriteString("null")
 928		return
 929	}
 930
 931	// EDIT(end)
 932	if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
 933		// We're a large number of nested ptrEncoder.encode calls deep;
 934		// start checking if we've run into a pointer cycle.
 935		ptr := v.Interface()
 936		if _, ok := e.ptrSeen[ptr]; ok {
 937			e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
 938		}
 939		e.ptrSeen[ptr] = struct{}{}
 940		defer delete(e.ptrSeen, ptr)
 941	}
 942	pe.elemEnc(e, v.Elem(), opts)
 943	e.ptrLevel--
 944}
 945
 946func newPtrEncoder(t reflect.Type) encoderFunc {
 947	enc := ptrEncoder{typeEncoder(t.Elem())}
 948	return enc.encode
 949}
 950
 951type condAddrEncoder struct {
 952	canAddrEnc, elseEnc encoderFunc
 953}
 954
 955func (ce condAddrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
 956	if v.CanAddr() {
 957		ce.canAddrEnc(e, v, opts)
 958	} else {
 959		ce.elseEnc(e, v, opts)
 960	}
 961}
 962
 963// newCondAddrEncoder returns an encoder that checks whether its value
 964// CanAddr and delegates to canAddrEnc if so, else to elseEnc.
 965func newCondAddrEncoder(canAddrEnc, elseEnc encoderFunc) encoderFunc {
 966	enc := condAddrEncoder{canAddrEnc: canAddrEnc, elseEnc: elseEnc}
 967	return enc.encode
 968}
 969
 970func isValidTag(s string) bool {
 971	if s == "" {
 972		return false
 973	}
 974	for _, c := range s {
 975		switch {
 976		case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
 977			// Backslash and quote chars are reserved, but
 978			// otherwise any punctuation chars are allowed
 979			// in a tag name.
 980		case !unicode.IsLetter(c) && !unicode.IsDigit(c):
 981			return false
 982		}
 983	}
 984	return true
 985}
 986
 987func typeByIndex(t reflect.Type, index []int) reflect.Type {
 988	for _, i := range index {
 989		if t.Kind() == reflect.Pointer {
 990			t = t.Elem()
 991		}
 992		t = t.Field(i).Type
 993	}
 994	return t
 995}
 996
 997type reflectWithString struct {
 998	v  reflect.Value
 999	ks string
1000}
1001
1002func resolveKeyName(k reflect.Value) (string, error) {
1003	if k.Kind() == reflect.String {
1004		return k.String(), nil
1005	}
1006	if tm, ok := k.Interface().(encoding.TextMarshaler); ok {
1007		if k.Kind() == reflect.Pointer && k.IsNil() {
1008			return "", nil
1009		}
1010		buf, err := tm.MarshalText()
1011		return string(buf), err
1012	}
1013	switch k.Kind() {
1014	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1015		return strconv.FormatInt(k.Int(), 10), nil
1016	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1017		return strconv.FormatUint(k.Uint(), 10), nil
1018	}
1019	panic("unexpected map key type")
1020}
1021
1022func appendString[Bytes []byte | string](dst []byte, src Bytes, escapeHTML bool) []byte {
1023	dst = append(dst, '"')
1024	start := 0
1025	for i := 0; i < len(src); {
1026		if b := src[i]; b < utf8.RuneSelf {
1027			if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) {
1028				i++
1029				continue
1030			}
1031			dst = append(dst, src[start:i]...)
1032			switch b {
1033			case '\\', '"':
1034				dst = append(dst, '\\', b)
1035			case '\b':
1036				dst = append(dst, '\\', 'b')
1037			case '\f':
1038				dst = append(dst, '\\', 'f')
1039			case '\n':
1040				dst = append(dst, '\\', 'n')
1041			case '\r':
1042				dst = append(dst, '\\', 'r')
1043			case '\t':
1044				dst = append(dst, '\\', 't')
1045			default:
1046				// This encodes bytes < 0x20 except for \b, \f, \n, \r and \t.
1047				// If escapeHTML is set, it also escapes <, >, and &
1048				// because they can lead to security holes when
1049				// user-controlled strings are rendered into JSON
1050				// and served to some browsers.
1051				dst = append(dst, '\\', 'u', '0', '0', hex[b>>4], hex[b&0xF])
1052			}
1053			i++
1054			start = i
1055			continue
1056		}
1057		// TODO(https://go.dev/issue/56948): Use generic utf8 functionality.
1058		// For now, cast only a small portion of byte slices to a string
1059		// so that it can be stack allocated. This slows down []byte slightly
1060		// due to the extra copy, but keeps string performance roughly the same.
1061		n := len(src) - i
1062		if n > utf8.UTFMax {
1063			n = utf8.UTFMax
1064		}
1065		c, size := utf8.DecodeRuneInString(string(src[i : i+n]))
1066		if c == utf8.RuneError && size == 1 {
1067			dst = append(dst, src[start:i]...)
1068			dst = append(dst, `\ufffd`...)
1069			i += size
1070			start = i
1071			continue
1072		}
1073		// U+2028 is LINE SEPARATOR.
1074		// U+2029 is PARAGRAPH SEPARATOR.
1075		// They are both technically valid characters in JSON strings,
1076		// but don't work in JSONP, which has to be evaluated as JavaScript,
1077		// and can lead to security holes there. It is valid JSON to
1078		// escape them, so we do so unconditionally.
1079		// See https://en.wikipedia.org/wiki/JSON#Safety.
1080		if c == '\u2028' || c == '\u2029' {
1081			dst = append(dst, src[start:i]...)
1082			dst = append(dst, '\\', 'u', '2', '0', '2', hex[c&0xF])
1083			i += size
1084			start = i
1085			continue
1086		}
1087		i += size
1088	}
1089	dst = append(dst, src[start:]...)
1090	dst = append(dst, '"')
1091	return dst
1092}
1093
1094// A field represents a single field found in a struct.
1095type field struct {
1096	name      string
1097	nameBytes []byte // []byte(name)
1098
1099	nameNonEsc  string // `"` + name + `":`
1100	nameEscHTML string // `"` + HTMLEscape(name) + `":`
1101
1102	tag       bool
1103	index     []int
1104	typ       reflect.Type
1105	omitEmpty bool
1106	omitZero  bool
1107	isZero    func(reflect.Value) bool
1108	quoted    bool
1109
1110	encoder encoderFunc
1111
1112	// EDIT(begin): save the timefmt if present
1113	timefmt string
1114	// EDIT(end)
1115}
1116
1117type isZeroer interface {
1118	IsZero() bool
1119}
1120
1121// SHIM(reflect): TypeFor[T]() reflect.Type
1122var isZeroerType = shims.TypeFor[isZeroer]()
1123
1124// typeFields returns a list of fields that JSON should recognize for the given type.
1125// The algorithm is breadth-first search over the set of structs to include - the top struct
1126// and then any reachable anonymous structs.
1127//
1128// typeFields should be an internal detail,
1129// but widely used packages access it using linkname.
1130// Notable members of the hall of shame include:
1131//   - github.com/bytedance/sonic
1132//
1133// Do not remove or change the type signature.
1134// See go.dev/issue/67401.
1135//
1136//go:linkname typeFields
1137func typeFields(t reflect.Type) structFields {
1138	// Anonymous fields to explore at the current level and the next.
1139	current := []field{}
1140	next := []field{{typ: t}}
1141
1142	// Count of queued names for current level and the next.
1143	var count, nextCount map[reflect.Type]int
1144
1145	// Types already visited at an earlier level.
1146	visited := map[reflect.Type]bool{}
1147
1148	// Fields found.
1149	var fields []field
1150
1151	// Buffer to run appendHTMLEscape on field names.
1152	var nameEscBuf []byte
1153
1154	for len(next) > 0 {
1155		current, next = next, current[:0]
1156		count, nextCount = nextCount, map[reflect.Type]int{}
1157
1158		for _, f := range current {
1159			if visited[f.typ] {
1160				continue
1161			}
1162			visited[f.typ] = true
1163
1164			// Scan f.typ for fields to include.
1165			for i := 0; i < f.typ.NumField(); i++ {
1166				sf := f.typ.Field(i)
1167				if sf.Anonymous {
1168					t := sf.Type
1169					if t.Kind() == reflect.Pointer {
1170						t = t.Elem()
1171					}
1172					if !sf.IsExported() && t.Kind() != reflect.Struct {
1173						// Ignore embedded fields of unexported non-struct types.
1174						continue
1175					}
1176					// Do not ignore embedded fields of unexported struct types
1177					// since they may have exported fields.
1178				} else if !sf.IsExported() {
1179					// Ignore unexported non-embedded fields.
1180					continue
1181				}
1182				tag := sf.Tag.Get("json")
1183				if tag == "-" {
1184					continue
1185				}
1186				name, opts := parseTag(tag)
1187				if !isValidTag(name) {
1188					name = ""
1189				}
1190				index := make([]int, len(f.index)+1)
1191				copy(index, f.index)
1192				index[len(f.index)] = i
1193
1194				ft := sf.Type
1195				if ft.Name() == "" && ft.Kind() == reflect.Pointer {
1196					// Follow pointer.
1197					ft = ft.Elem()
1198				}
1199
1200				// Only strings, floats, integers, and booleans can be quoted.
1201				quoted := false
1202				if opts.Contains("string") {
1203					switch ft.Kind() {
1204					case reflect.Bool,
1205						reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
1206						reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
1207						reflect.Float32, reflect.Float64,
1208						reflect.String:
1209						quoted = true
1210					}
1211				}
1212
1213				// Record found field and index sequence.
1214				if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
1215					tagged := name != ""
1216					if name == "" {
1217						name = sf.Name
1218					}
1219					field := field{
1220						name:      name,
1221						tag:       tagged,
1222						index:     index,
1223						typ:       ft,
1224						omitEmpty: opts.Contains("omitempty"),
1225						omitZero:  opts.Contains("omitzero"),
1226						quoted:    quoted,
1227						// EDIT(begin): save the timefmt
1228						timefmt: sf.Tag.Get("format"),
1229						// EDIT(end)
1230					}
1231					field.nameBytes = []byte(field.name)
1232
1233					// Build nameEscHTML and nameNonEsc ahead of time.
1234					nameEscBuf = appendHTMLEscape(nameEscBuf[:0], field.nameBytes)
1235					field.nameEscHTML = `"` + string(nameEscBuf) + `":`
1236					field.nameNonEsc = `"` + field.name + `":`
1237
1238					if field.omitZero {
1239						t := sf.Type
1240						// Provide a function that uses a type's IsZero method.
1241						switch {
1242						case t.Kind() == reflect.Interface && t.Implements(isZeroerType):
1243							field.isZero = func(v reflect.Value) bool {
1244								// Avoid panics calling IsZero on a nil interface or
1245								// non-nil interface with nil pointer.
1246								return v.IsNil() ||
1247									(v.Elem().Kind() == reflect.Pointer && v.Elem().IsNil()) ||
1248									v.Interface().(isZeroer).IsZero()
1249							}
1250						case t.Kind() == reflect.Pointer && t.Implements(isZeroerType):
1251							field.isZero = func(v reflect.Value) bool {
1252								// Avoid panics calling IsZero on nil pointer.
1253								return v.IsNil() || v.Interface().(isZeroer).IsZero()
1254							}
1255						case t.Implements(isZeroerType):
1256							field.isZero = func(v reflect.Value) bool {
1257								return v.Interface().(isZeroer).IsZero()
1258							}
1259						case reflect.PointerTo(t).Implements(isZeroerType):
1260							field.isZero = func(v reflect.Value) bool {
1261								if !v.CanAddr() {
1262									// Temporarily box v so we can take the address.
1263									v2 := reflect.New(v.Type()).Elem()
1264									v2.Set(v)
1265									v = v2
1266								}
1267								return v.Addr().Interface().(isZeroer).IsZero()
1268							}
1269						}
1270					}
1271
1272					fields = append(fields, field)
1273					if count[f.typ] > 1 {
1274						// If there were multiple instances, add a second,
1275						// so that the annihilation code will see a duplicate.
1276						// It only cares about the distinction between 1 and 2,
1277						// so don't bother generating any more copies.
1278						fields = append(fields, fields[len(fields)-1])
1279					}
1280					continue
1281				}
1282
1283				// Record new anonymous struct to explore in next round.
1284				nextCount[ft]++
1285				if nextCount[ft] == 1 {
1286					next = append(next, field{name: ft.Name(), index: index, typ: ft})
1287				}
1288			}
1289		}
1290	}
1291
1292	slices.SortFunc(fields, func(a, b field) int {
1293		// sort field by name, breaking ties with depth, then
1294		// breaking ties with "name came from json tag", then
1295		// breaking ties with index sequence.
1296		if c := strings.Compare(a.name, b.name); c != 0 {
1297			return c
1298		}
1299		if c := cmp.Compare(len(a.index), len(b.index)); c != 0 {
1300			return c
1301		}
1302		if a.tag != b.tag {
1303			if a.tag {
1304				return -1
1305			}
1306			return +1
1307		}
1308		return slices.Compare(a.index, b.index)
1309	})
1310
1311	// Delete all fields that are hidden by the Go rules for embedded fields,
1312	// except that fields with JSON tags are promoted.
1313
1314	// The fields are sorted in primary order of name, secondary order
1315	// of field index length. Loop over names; for each name, delete
1316	// hidden fields by choosing the one dominant field that survives.
1317	out := fields[:0]
1318	for advance, i := 0, 0; i < len(fields); i += advance {
1319		// One iteration per name.
1320		// Find the sequence of fields with the name of this first field.
1321		fi := fields[i]
1322		name := fi.name
1323		for advance = 1; i+advance < len(fields); advance++ {
1324			fj := fields[i+advance]
1325			if fj.name != name {
1326				break
1327			}
1328		}
1329		if advance == 1 { // Only one field with this name
1330			out = append(out, fi)
1331			continue
1332		}
1333		dominant, ok := dominantField(fields[i : i+advance])
1334		if ok {
1335			out = append(out, dominant)
1336		}
1337	}
1338
1339	fields = out
1340	slices.SortFunc(fields, func(i, j field) int {
1341		return slices.Compare(i.index, j.index)
1342	})
1343
1344	for i := range fields {
1345		f := &fields[i]
1346		f.encoder = typeEncoder(typeByIndex(t, f.index))
1347
1348		// EDIT(begin): add custom timefmt if necessary
1349		if f.timefmt != "" {
1350			f.encoder = continueWithTimeFmt(f.timefmt, f.encoder)
1351		}
1352		// EDIT(end)
1353	}
1354	exactNameIndex := make(map[string]*field, len(fields))
1355	foldedNameIndex := make(map[string]*field, len(fields))
1356	for i, field := range fields {
1357		exactNameIndex[field.name] = &fields[i]
1358		// For historical reasons, first folded match takes precedence.
1359		if _, ok := foldedNameIndex[string(foldName(field.nameBytes))]; !ok {
1360			foldedNameIndex[string(foldName(field.nameBytes))] = &fields[i]
1361		}
1362	}
1363	return structFields{fields, exactNameIndex, foldedNameIndex}
1364}
1365
1366// dominantField looks through the fields, all of which are known to
1367// have the same name, to find the single field that dominates the
1368// others using Go's embedding rules, modified by the presence of
1369// JSON tags. If there are multiple top-level fields, the boolean
1370// will be false: This condition is an error in Go and we skip all
1371// the fields.
1372func dominantField(fields []field) (field, bool) {
1373	// The fields are sorted in increasing index-length order, then by presence of tag.
1374	// That means that the first field is the dominant one. We need only check
1375	// for error cases: two fields at top level, either both tagged or neither tagged.
1376	if len(fields) > 1 && len(fields[0].index) == len(fields[1].index) && fields[0].tag == fields[1].tag {
1377		return field{}, false
1378	}
1379	return fields[0], true
1380}
1381
1382var fieldCache sync.Map // map[reflect.Type]structFields
1383
1384// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
1385func cachedTypeFields(t reflect.Type) structFields {
1386	if f, ok := fieldCache.Load(t); ok {
1387		return f.(structFields)
1388	}
1389	f, _ := fieldCache.LoadOrStore(t, typeFields(t))
1390	return f.(structFields)
1391}
1392
1393func mayAppendQuote(b []byte, quoted bool) []byte {
1394	if quoted {
1395		b = append(b, '"')
1396	}
1397	return b
1398}