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

View as plain text