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