Source file src/encoding/json/v2/arshal.go
1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build goexperiment.jsonv2 6 7 package json 8 9 import ( 10 "bytes" 11 "encoding" 12 "io" 13 "reflect" 14 "slices" 15 "strings" 16 "sync" 17 "time" 18 19 "encoding/json/internal" 20 "encoding/json/internal/jsonflags" 21 "encoding/json/internal/jsonopts" 22 "encoding/json/jsontext" 23 ) 24 25 // Reference encoding and time packages to assist pkgsite 26 // in being able to hotlink references to those packages. 27 var ( 28 _ encoding.TextMarshaler 29 _ encoding.TextAppender 30 _ encoding.TextUnmarshaler 31 _ time.Time 32 _ time.Duration 33 ) 34 35 // export exposes internal functionality of the "jsontext" package. 36 var export = jsontext.Internal.Export(&internal.AllowInternalUse) 37 38 // Marshal serializes a Go value as a []byte according to the provided 39 // marshal and encode options (while ignoring unmarshal or decode options). 40 // It does not terminate the output with a newline. 41 // 42 // Type-specific marshal functions and methods take precedence 43 // over the default representation of a value. 44 // Functions or methods that operate on *T are only called when encoding 45 // a value of type T (by taking its address) or a non-nil value of *T. 46 // Marshal ensures that a value is always addressable 47 // (by boxing it on the heap if necessary) so that 48 // these functions and methods can be consistently called. For performance, 49 // it is recommended that Marshal be passed a non-nil pointer to the value. 50 // 51 // The input value is encoded as JSON according the following rules: 52 // 53 // - If any type-specific functions in a [WithMarshalers] option match 54 // the value type, then those functions are called to encode the value. 55 // If all applicable functions return [SkipFunc], 56 // then the value is encoded according to subsequent rules. 57 // 58 // - If the value type implements [MarshalerTo], 59 // then the MarshalJSONTo method is called to encode the value. 60 // 61 // - If the value type implements [Marshaler], 62 // then the MarshalJSON method is called to encode the value. 63 // 64 // - If the value type implements [encoding.TextAppender], 65 // then the AppendText method is called to encode the value and 66 // subsequently encode its result as a JSON string. 67 // 68 // - If the value type implements [encoding.TextMarshaler], 69 // then the MarshalText method is called to encode the value and 70 // subsequently encode its result as a JSON string. 71 // 72 // - Otherwise, the value is encoded according to the value's type 73 // as described in detail below. 74 // 75 // Most Go types have a default JSON representation. 76 // Certain types support specialized formatting according to 77 // a format flag optionally specified in the Go struct tag 78 // for the struct field that contains the current value 79 // (see the “JSON Representation of Go structs” section for more details). 80 // 81 // The representation of each type is as follows: 82 // 83 // - A Go boolean is encoded as a JSON boolean (e.g., true or false). 84 // It does not support any custom format flags. 85 // 86 // - A Go string is encoded as a JSON string. 87 // It does not support any custom format flags. 88 // 89 // - A Go []byte or [N]byte is encoded as a JSON string containing 90 // the binary value encoded using RFC 4648. 91 // If the format is "base64" or unspecified, then this uses RFC 4648, section 4. 92 // If the format is "base64url", then this uses RFC 4648, section 5. 93 // If the format is "base32", then this uses RFC 4648, section 6. 94 // If the format is "base32hex", then this uses RFC 4648, section 7. 95 // If the format is "base16" or "hex", then this uses RFC 4648, section 8. 96 // If the format is "array", then the bytes value is encoded as a JSON array 97 // where each byte is recursively JSON-encoded as each JSON array element. 98 // 99 // - A Go integer is encoded as a JSON number without fractions or exponents. 100 // If [StringifyNumbers] is specified or encoding a JSON object name, 101 // then the JSON number is encoded within a JSON string. 102 // It does not support any custom format flags. 103 // 104 // - A Go float is encoded as a JSON number. 105 // If [StringifyNumbers] is specified or encoding a JSON object name, 106 // then the JSON number is encoded within a JSON string. 107 // If the format is "nonfinite", then NaN, +Inf, and -Inf are encoded as 108 // the JSON strings "NaN", "Infinity", and "-Infinity", respectively. 109 // Otherwise, the presence of non-finite numbers results in a [SemanticError]. 110 // 111 // - A Go map is encoded as a JSON object, where each Go map key and value 112 // is recursively encoded as a name and value pair in the JSON object. 113 // The Go map key must encode as a JSON string, otherwise this results 114 // in a [SemanticError]. The Go map is traversed in a non-deterministic order. 115 // For deterministic encoding, consider using the [Deterministic] option. 116 // If the format is "emitnull", then a nil map is encoded as a JSON null. 117 // If the format is "emitempty", then a nil map is encoded as an empty JSON object, 118 // regardless of whether [FormatNilMapAsNull] is specified. 119 // Otherwise by default, a nil map is encoded as an empty JSON object. 120 // 121 // - A Go struct is encoded as a JSON object. 122 // See the “JSON Representation of Go structs” section 123 // in the package-level documentation for more details. 124 // 125 // - A Go slice is encoded as a JSON array, where each Go slice element 126 // is recursively JSON-encoded as the elements of the JSON array. 127 // If the format is "emitnull", then a nil slice is encoded as a JSON null. 128 // If the format is "emitempty", then a nil slice is encoded as an empty JSON array, 129 // regardless of whether [FormatNilSliceAsNull] is specified. 130 // Otherwise by default, a nil slice is encoded as an empty JSON array. 131 // 132 // - A Go array is encoded as a JSON array, where each Go array element 133 // is recursively JSON-encoded as the elements of the JSON array. 134 // The JSON array length is always identical to the Go array length. 135 // It does not support any custom format flags. 136 // 137 // - A Go pointer is encoded as a JSON null if nil, otherwise it is 138 // the recursively JSON-encoded representation of the underlying value. 139 // Format flags are forwarded to the encoding of the underlying value. 140 // 141 // - A Go interface is encoded as a JSON null if nil, otherwise it is 142 // the recursively JSON-encoded representation of the underlying value. 143 // It does not support any custom format flags. 144 // 145 // - A Go [time.Time] is encoded as a JSON string containing the timestamp 146 // formatted in RFC 3339 with nanosecond precision. 147 // If the format matches one of the format constants declared 148 // in the time package (e.g., RFC1123), then that format is used. 149 // If the format is "unix", "unixmilli", "unixmicro", or "unixnano", 150 // then the timestamp is encoded as a JSON number of the number of seconds 151 // (or milliseconds, microseconds, or nanoseconds) since the Unix epoch, 152 // which is January 1st, 1970 at 00:00:00 UTC. 153 // Otherwise, the format is used as-is with [time.Time.Format] if non-empty. 154 // 155 // - A Go [time.Duration] is encoded as a JSON string containing the duration 156 // formatted according to [time.Duration.String]. 157 // If the format is "sec", "milli", "micro", or "nano", 158 // then the duration is encoded as a JSON number of the number of seconds 159 // (or milliseconds, microseconds, or nanoseconds) in the duration. 160 // If the format is "units", it uses [time.Duration.String]. 161 // 162 // - All other Go types (e.g., complex numbers, channels, and functions) 163 // have no default representation and result in a [SemanticError]. 164 // 165 // JSON cannot represent cyclic data structures and Marshal does not handle them. 166 // Passing cyclic structures will result in an error. 167 func Marshal(in any, opts ...Options) (out []byte, err error) { 168 enc := export.GetBufferedEncoder(opts...) 169 defer export.PutBufferedEncoder(enc) 170 xe := export.Encoder(enc) 171 xe.Flags.Set(jsonflags.OmitTopLevelNewline | 1) 172 err = marshalEncode(enc, in, &xe.Struct) 173 if err != nil && xe.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { 174 return nil, internal.TransformMarshalError(in, err) 175 } 176 return bytes.Clone(xe.Buf), err 177 } 178 179 // MarshalWrite serializes a Go value into an [io.Writer] according to the provided 180 // marshal and encode options (while ignoring unmarshal or decode options). 181 // It does not terminate the output with a newline. 182 // See [Marshal] for details about the conversion of a Go value into JSON. 183 func MarshalWrite(out io.Writer, in any, opts ...Options) (err error) { 184 enc := export.GetStreamingEncoder(out, opts...) 185 defer export.PutStreamingEncoder(enc) 186 xe := export.Encoder(enc) 187 xe.Flags.Set(jsonflags.OmitTopLevelNewline | 1) 188 err = marshalEncode(enc, in, &xe.Struct) 189 if err != nil && xe.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { 190 return internal.TransformMarshalError(in, err) 191 } 192 return err 193 } 194 195 // MarshalEncode serializes a Go value into an [jsontext.Encoder] according to 196 // the provided marshal options (while ignoring unmarshal, encode, or decode options). 197 // Any marshal-relevant options already specified on the [jsontext.Encoder] 198 // take lower precedence than the set of options provided by the caller. 199 // Unlike [Marshal] and [MarshalWrite], encode options are ignored because 200 // they must have already been specified on the provided [jsontext.Encoder]. 201 // 202 // See [Marshal] for details about the conversion of a Go value into JSON. 203 func MarshalEncode(out *jsontext.Encoder, in any, opts ...Options) (err error) { 204 xe := export.Encoder(out) 205 if len(opts) > 0 { 206 optsOriginal := xe.Struct 207 defer func() { xe.Struct = optsOriginal }() 208 xe.Struct.JoinWithoutCoderOptions(opts...) 209 } 210 err = marshalEncode(out, in, &xe.Struct) 211 if err != nil && xe.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { 212 return internal.TransformMarshalError(in, err) 213 } 214 return err 215 } 216 217 func marshalEncode(out *jsontext.Encoder, in any, mo *jsonopts.Struct) (err error) { 218 v := reflect.ValueOf(in) 219 if !v.IsValid() || (v.Kind() == reflect.Pointer && v.IsNil()) { 220 return out.WriteToken(jsontext.Null) 221 } 222 // Shallow copy non-pointer values to obtain an addressable value. 223 // It is beneficial to performance to always pass pointers to avoid this. 224 forceAddr := v.Kind() != reflect.Pointer 225 if forceAddr { 226 v2 := reflect.New(v.Type()) 227 v2.Elem().Set(v) 228 v = v2 229 } 230 va := addressableValue{v.Elem(), forceAddr} // dereferenced pointer is always addressable 231 t := va.Type() 232 233 // Lookup and call the marshal function for this type. 234 marshal := lookupArshaler(t).marshal 235 if mo.Marshalers != nil { 236 marshal, _ = mo.Marshalers.(*Marshalers).lookup(marshal, t) 237 } 238 if err := marshal(out, va, mo); err != nil { 239 if !mo.Flags.Get(jsonflags.AllowDuplicateNames) { 240 export.Encoder(out).Tokens.InvalidateDisabledNamespaces() 241 } 242 return err 243 } 244 return nil 245 } 246 247 // Unmarshal decodes a []byte input into a Go value according to the provided 248 // unmarshal and decode options (while ignoring marshal or encode options). 249 // The input must be a single JSON value with optional whitespace interspersed. 250 // The output must be a non-nil pointer. 251 // 252 // Type-specific unmarshal functions and methods take precedence 253 // over the default representation of a value. 254 // Functions or methods that operate on *T are only called when decoding 255 // a value of type T (by taking its address) or a non-nil value of *T. 256 // Unmarshal ensures that a value is always addressable 257 // (by boxing it on the heap if necessary) so that 258 // these functions and methods can be consistently called. 259 // 260 // The input is decoded into the output according the following rules: 261 // 262 // - If any type-specific functions in a [WithUnmarshalers] option match 263 // the value type, then those functions are called to decode the JSON 264 // value. If all applicable functions return [SkipFunc], 265 // then the input is decoded according to subsequent rules. 266 // 267 // - If the value type implements [UnmarshalerFrom], 268 // then the UnmarshalJSONFrom method is called to decode the JSON value. 269 // 270 // - If the value type implements [Unmarshaler], 271 // then the UnmarshalJSON method is called to decode the JSON value. 272 // 273 // - If the value type implements [encoding.TextUnmarshaler], 274 // then the input is decoded as a JSON string and 275 // the UnmarshalText method is called with the decoded string value. 276 // This fails with a [SemanticError] if the input is not a JSON string. 277 // 278 // - Otherwise, the JSON value is decoded according to the value's type 279 // as described in detail below. 280 // 281 // Most Go types have a default JSON representation. 282 // Certain types support specialized formatting according to 283 // a format flag optionally specified in the Go struct tag 284 // for the struct field that contains the current value 285 // (see the “JSON Representation of Go structs” section for more details). 286 // A JSON null may be decoded into every supported Go value where 287 // it is equivalent to storing the zero value of the Go value. 288 // If the input JSON kind is not handled by the current Go value type, 289 // then this fails with a [SemanticError]. Unless otherwise specified, 290 // the decoded value replaces any pre-existing value. 291 // 292 // The representation of each type is as follows: 293 // 294 // - A Go boolean is decoded from a JSON boolean (e.g., true or false). 295 // It does not support any custom format flags. 296 // 297 // - A Go string is decoded from a JSON string. 298 // It does not support any custom format flags. 299 // 300 // - A Go []byte or [N]byte is decoded from a JSON string 301 // containing the binary value encoded using RFC 4648. 302 // If the format is "base64" or unspecified, then this uses RFC 4648, section 4. 303 // If the format is "base64url", then this uses RFC 4648, section 5. 304 // If the format is "base32", then this uses RFC 4648, section 6. 305 // If the format is "base32hex", then this uses RFC 4648, section 7. 306 // If the format is "base16" or "hex", then this uses RFC 4648, section 8. 307 // If the format is "array", then the Go slice or array is decoded from a 308 // JSON array where each JSON element is recursively decoded for each byte. 309 // When decoding into a non-nil []byte, the slice length is reset to zero 310 // and the decoded input is appended to it. 311 // When decoding into a [N]byte, the input must decode to exactly N bytes, 312 // otherwise it fails with a [SemanticError]. 313 // 314 // - A Go integer is decoded from a JSON number. 315 // It must be decoded from a JSON string containing a JSON number 316 // if [StringifyNumbers] is specified or decoding a JSON object name. 317 // It fails with a [SemanticError] if the JSON number 318 // has a fractional or exponent component. 319 // It also fails if it overflows the representation of the Go integer type. 320 // It does not support any custom format flags. 321 // 322 // - A Go float is decoded from a JSON number. 323 // It must be decoded from a JSON string containing a JSON number 324 // if [StringifyNumbers] is specified or decoding a JSON object name. 325 // It fails if it overflows the representation of the Go float type. 326 // If the format is "nonfinite", then the JSON strings 327 // "NaN", "Infinity", and "-Infinity" are decoded as NaN, +Inf, and -Inf. 328 // Otherwise, the presence of such strings results in a [SemanticError]. 329 // 330 // - A Go map is decoded from a JSON object, 331 // where each JSON object name and value pair is recursively decoded 332 // as the Go map key and value. Maps are not cleared. 333 // If the Go map is nil, then a new map is allocated to decode into. 334 // If the decoded key matches an existing Go map entry, the entry value 335 // is reused by decoding the JSON object value into it. 336 // The formats "emitnull" and "emitempty" have no effect when decoding. 337 // 338 // - A Go struct is decoded from a JSON object. 339 // See the “JSON Representation of Go structs” section 340 // in the package-level documentation for more details. 341 // 342 // - A Go slice is decoded from a JSON array, where each JSON element 343 // is recursively decoded and appended to the Go slice. 344 // Before appending into a Go slice, a new slice is allocated if it is nil, 345 // otherwise the slice length is reset to zero. 346 // The formats "emitnull" and "emitempty" have no effect when decoding. 347 // 348 // - A Go array is decoded from a JSON array, where each JSON array element 349 // is recursively decoded as each corresponding Go array element. 350 // Each Go array element is zeroed before decoding into it. 351 // It fails with a [SemanticError] if the JSON array does not contain 352 // the exact same number of elements as the Go array. 353 // It does not support any custom format flags. 354 // 355 // - A Go pointer is decoded based on the JSON kind and underlying Go type. 356 // If the input is a JSON null, then this stores a nil pointer. 357 // Otherwise, it allocates a new underlying value if the pointer is nil, 358 // and recursively JSON decodes into the underlying value. 359 // Format flags are forwarded to the decoding of the underlying type. 360 // 361 // - A Go interface is decoded based on the JSON kind and underlying Go type. 362 // If the input is a JSON null, then this stores a nil interface value. 363 // Otherwise, a nil interface value of an empty interface type is initialized 364 // with a zero Go bool, string, float64, map[string]any, or []any if the 365 // input is a JSON boolean, string, number, object, or array, respectively. 366 // If the interface value is still nil, then this fails with a [SemanticError] 367 // since decoding could not determine an appropriate Go type to decode into. 368 // For example, unmarshaling into a nil io.Reader fails since 369 // there is no concrete type to populate the interface value with. 370 // Otherwise an underlying value exists and it recursively decodes 371 // the JSON input into it. It does not support any custom format flags. 372 // 373 // - A Go [time.Time] is decoded from a JSON string containing the time 374 // formatted in RFC 3339 with nanosecond precision. 375 // If the format matches one of the format constants declared in 376 // the time package (e.g., RFC1123), then that format is used for parsing. 377 // If the format is "unix", "unixmilli", "unixmicro", or "unixnano", 378 // then the timestamp is decoded from a JSON number of the number of seconds 379 // (or milliseconds, microseconds, or nanoseconds) since the Unix epoch, 380 // which is January 1st, 1970 at 00:00:00 UTC. 381 // Otherwise, the format is used as-is with [time.Time.Parse] if non-empty. 382 // 383 // - A Go [time.Duration] is decoded from a JSON string by 384 // passing the decoded string to [time.ParseDuration]. 385 // If the format is "sec", "milli", "micro", or "nano", 386 // then the duration is decoded from a JSON number of the number of seconds 387 // (or milliseconds, microseconds, or nanoseconds) in the duration. 388 // If the format is "units", it uses [time.ParseDuration]. 389 // 390 // - All other Go types (e.g., complex numbers, channels, and functions) 391 // have no default representation and result in a [SemanticError]. 392 // 393 // In general, unmarshaling follows merge semantics (similar to RFC 7396) 394 // where the decoded Go value replaces the destination value 395 // for any JSON kind other than an object. 396 // For JSON objects, the input object is merged into the destination value 397 // where matching object members recursively apply merge semantics. 398 func Unmarshal(in []byte, out any, opts ...Options) (err error) { 399 dec := export.GetBufferedDecoder(in, opts...) 400 defer export.PutBufferedDecoder(dec) 401 xd := export.Decoder(dec) 402 err = unmarshalFull(dec, out, &xd.Struct) 403 if err != nil && xd.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { 404 return internal.TransformUnmarshalError(out, err) 405 } 406 return err 407 } 408 409 // UnmarshalRead deserializes a Go value from an [io.Reader] according to the 410 // provided unmarshal and decode options (while ignoring marshal or encode options). 411 // The input must be a single JSON value with optional whitespace interspersed. 412 // It consumes the entirety of [io.Reader] until [io.EOF] is encountered, 413 // without reporting an error for EOF. The output must be a non-nil pointer. 414 // See [Unmarshal] for details about the conversion of JSON into a Go value. 415 func UnmarshalRead(in io.Reader, out any, opts ...Options) (err error) { 416 dec := export.GetStreamingDecoder(in, opts...) 417 defer export.PutStreamingDecoder(dec) 418 xd := export.Decoder(dec) 419 err = unmarshalFull(dec, out, &xd.Struct) 420 if err != nil && xd.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { 421 return internal.TransformUnmarshalError(out, err) 422 } 423 return err 424 } 425 426 func unmarshalFull(in *jsontext.Decoder, out any, uo *jsonopts.Struct) error { 427 switch err := unmarshalDecode(in, out, uo); err { 428 case nil: 429 return export.Decoder(in).CheckEOF() 430 case io.EOF: 431 return io.ErrUnexpectedEOF 432 default: 433 return err 434 } 435 } 436 437 // UnmarshalDecode deserializes a Go value from a [jsontext.Decoder] according to 438 // the provided unmarshal options (while ignoring marshal, encode, or decode options). 439 // Any unmarshal options already specified on the [jsontext.Decoder] 440 // take lower precedence than the set of options provided by the caller. 441 // Unlike [Unmarshal] and [UnmarshalRead], decode options are ignored because 442 // they must have already been specified on the provided [jsontext.Decoder]. 443 // 444 // The input may be a stream of one or more JSON values, 445 // where this only unmarshals the next JSON value in the stream. 446 // The output must be a non-nil pointer. 447 // See [Unmarshal] for details about the conversion of JSON into a Go value. 448 func UnmarshalDecode(in *jsontext.Decoder, out any, opts ...Options) (err error) { 449 xd := export.Decoder(in) 450 if len(opts) > 0 { 451 optsOriginal := xd.Struct 452 defer func() { xd.Struct = optsOriginal }() 453 xd.Struct.JoinWithoutCoderOptions(opts...) 454 } 455 err = unmarshalDecode(in, out, &xd.Struct) 456 if err != nil && xd.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { 457 return internal.TransformUnmarshalError(out, err) 458 } 459 return err 460 } 461 462 func unmarshalDecode(in *jsontext.Decoder, out any, uo *jsonopts.Struct) (err error) { 463 v := reflect.ValueOf(out) 464 if v.Kind() != reflect.Pointer || v.IsNil() { 465 return &SemanticError{action: "unmarshal", GoType: reflect.TypeOf(out), Err: internal.ErrNonNilReference} 466 } 467 va := addressableValue{v.Elem(), false} // dereferenced pointer is always addressable 468 t := va.Type() 469 470 // In legacy semantics, the entirety of the next JSON value 471 // was validated before attempting to unmarshal it. 472 if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) { 473 if err := export.Decoder(in).CheckNextValue(); err != nil { 474 return err 475 } 476 } 477 478 // Lookup and call the unmarshal function for this type. 479 unmarshal := lookupArshaler(t).unmarshal 480 if uo.Unmarshalers != nil { 481 unmarshal, _ = uo.Unmarshalers.(*Unmarshalers).lookup(unmarshal, t) 482 } 483 if err := unmarshal(in, va, uo); err != nil { 484 if !uo.Flags.Get(jsonflags.AllowDuplicateNames) { 485 export.Decoder(in).Tokens.InvalidateDisabledNamespaces() 486 } 487 return err 488 } 489 return nil 490 } 491 492 // addressableValue is a reflect.Value that is guaranteed to be addressable 493 // such that calling the Addr and Set methods do not panic. 494 // 495 // There is no compile magic that enforces this property, 496 // but rather the need to construct this type makes it easier to examine each 497 // construction site to ensure that this property is upheld. 498 type addressableValue struct { 499 reflect.Value 500 501 // forcedAddr reports whether this value is addressable 502 // only through the use of [newAddressableValue]. 503 // This is only used for [jsonflags.CallMethodsWithLegacySemantics]. 504 forcedAddr bool 505 } 506 507 // newAddressableValue constructs a new addressable value of type t. 508 func newAddressableValue(t reflect.Type) addressableValue { 509 return addressableValue{reflect.New(t).Elem(), true} 510 } 511 512 // TODO: Remove *jsonopts.Struct argument from [marshaler] and [unmarshaler]. 513 // This can be directly accessed on the encoder or decoder. 514 515 // All marshal and unmarshal behavior is implemented using these signatures. 516 // The *jsonopts.Struct argument is guaranteed to identical to or at least 517 // a strict super-set of the options in Encoder.Struct or Decoder.Struct. 518 // It is identical for Marshal, Unmarshal, MarshalWrite, and UnmarshalRead. 519 // It is a super-set for MarshalEncode and UnmarshalDecode. 520 type ( 521 marshaler = func(*jsontext.Encoder, addressableValue, *jsonopts.Struct) error 522 unmarshaler = func(*jsontext.Decoder, addressableValue, *jsonopts.Struct) error 523 ) 524 525 type arshaler struct { 526 marshal marshaler 527 unmarshal unmarshaler 528 nonDefault bool 529 } 530 531 var lookupArshalerCache sync.Map // map[reflect.Type]*arshaler 532 533 func lookupArshaler(t reflect.Type) *arshaler { 534 if v, ok := lookupArshalerCache.Load(t); ok { 535 return v.(*arshaler) 536 } 537 538 fncs := makeDefaultArshaler(t) 539 fncs = makeMethodArshaler(fncs, t) 540 fncs = makeTimeArshaler(fncs, t) 541 542 // Use the last stored so that duplicate arshalers can be garbage collected. 543 v, _ := lookupArshalerCache.LoadOrStore(t, fncs) 544 return v.(*arshaler) 545 } 546 547 var stringsPools = &sync.Pool{New: func() any { return new(stringSlice) }} 548 549 type stringSlice []string 550 551 // getStrings returns a non-nil pointer to a slice with length n. 552 func getStrings(n int) *stringSlice { 553 s := stringsPools.Get().(*stringSlice) 554 if cap(*s) < n { 555 *s = make([]string, n) 556 } 557 *s = (*s)[:n] 558 return s 559 } 560 561 func putStrings(s *stringSlice) { 562 if cap(*s) > 1<<10 { 563 *s = nil // avoid pinning arbitrarily large amounts of memory 564 } 565 stringsPools.Put(s) 566 } 567 568 func (ss *stringSlice) Sort() { 569 slices.SortFunc(*ss, func(x, y string) int { return strings.Compare(x, y) }) 570 } 571