Source file src/encoding/json/v2/arshal_funcs.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  	"errors"
    11  	"fmt"
    12  	"io"
    13  	"reflect"
    14  	"sync"
    15  
    16  	"encoding/json/internal"
    17  	"encoding/json/internal/jsonflags"
    18  	"encoding/json/internal/jsonopts"
    19  	"encoding/json/jsontext"
    20  )
    21  
    22  var errUnsupportedMutation = errors.New("unsupported calls must not read or write any tokens")
    23  var errNonSingularValue = errors.New("must read or write exactly one value")
    24  
    25  // Marshalers is a list of functions that may override the marshal behavior
    26  // of specific types. Populate [WithMarshalers] to use it with
    27  // [Marshal], [MarshalWrite], or [MarshalEncode].
    28  // A nil *Marshalers is equivalent to an empty list.
    29  // There are no exported fields or methods on Marshalers.
    30  type Marshalers = typedMarshalers
    31  
    32  // JoinMarshalers constructs a flattened list of marshal functions.
    33  // If multiple functions in the list are applicable for a value of a given type,
    34  // then those earlier in the list take precedence over those that come later.
    35  // If a function returns [errors.ErrUnsupported],
    36  // then the next applicable function is called,
    37  // otherwise the default marshaling behavior is used.
    38  //
    39  // For example:
    40  //
    41  //	m1 := JoinMarshalers(f1, f2)
    42  //	m2 := JoinMarshalers(f0, m1, f3)     // equivalent to m3
    43  //	m3 := JoinMarshalers(f0, f1, f2, f3) // equivalent to m2
    44  func JoinMarshalers(ms ...*Marshalers) *Marshalers {
    45  	return newMarshalers(ms...)
    46  }
    47  
    48  // Unmarshalers is a list of functions that may override the unmarshal behavior
    49  // of specific types. Populate [WithUnmarshalers] to use it with
    50  // [Unmarshal], [UnmarshalRead], or [UnmarshalDecode].
    51  // A nil *Unmarshalers is equivalent to an empty list.
    52  // There are no exported fields or methods on Unmarshalers.
    53  type Unmarshalers = typedUnmarshalers
    54  
    55  // JoinUnmarshalers constructs a flattened list of unmarshal functions.
    56  // If multiple functions in the list are applicable for a value of a given type,
    57  // then those earlier in the list take precedence over those that come later.
    58  // If a function returns [errors.ErrUnsupported],
    59  // then the next applicable function is called,
    60  // otherwise the default unmarshaling behavior is used.
    61  //
    62  // For example:
    63  //
    64  //	u1 := JoinUnmarshalers(f1, f2)
    65  //	u2 := JoinUnmarshalers(f0, u1, f3)     // equivalent to u3
    66  //	u3 := JoinUnmarshalers(f0, f1, f2, f3) // equivalent to u2
    67  func JoinUnmarshalers(us ...*Unmarshalers) *Unmarshalers {
    68  	return newUnmarshalers(us...)
    69  }
    70  
    71  type typedMarshalers = typedArshalers[jsontext.Encoder]
    72  type typedUnmarshalers = typedArshalers[jsontext.Decoder]
    73  type typedArshalers[Coder any] struct {
    74  	nonComparable
    75  
    76  	fncVals  []typedArshaler[Coder]
    77  	fncCache sync.Map // map[reflect.Type]arshaler
    78  
    79  	// fromAny reports whether any of Go types used to represent arbitrary JSON
    80  	// (i.e., any, bool, string, float64, map[string]any, or []any) matches
    81  	// any of the provided type-specific arshalers.
    82  	//
    83  	// This bit of information is needed in arshal_default.go to determine
    84  	// whether to use the specialized logic in arshal_any.go to handle
    85  	// the any interface type. The logic in arshal_any.go does not support
    86  	// type-specific arshal functions, so we must avoid using that logic
    87  	// if this is true.
    88  	fromAny bool
    89  }
    90  type typedMarshaler = typedArshaler[jsontext.Encoder]
    91  type typedUnmarshaler = typedArshaler[jsontext.Decoder]
    92  type typedArshaler[Coder any] struct {
    93  	typ     reflect.Type
    94  	fnc     func(*Coder, addressableValue, *jsonopts.Struct) error
    95  	maySkip bool
    96  }
    97  
    98  func newMarshalers(ms ...*Marshalers) *Marshalers       { return newTypedArshalers(ms...) }
    99  func newUnmarshalers(us ...*Unmarshalers) *Unmarshalers { return newTypedArshalers(us...) }
   100  func newTypedArshalers[Coder any](as ...*typedArshalers[Coder]) *typedArshalers[Coder] {
   101  	var a typedArshalers[Coder]
   102  	for _, a2 := range as {
   103  		if a2 != nil {
   104  			a.fncVals = append(a.fncVals, a2.fncVals...)
   105  			a.fromAny = a.fromAny || a2.fromAny
   106  		}
   107  	}
   108  	if len(a.fncVals) == 0 {
   109  		return nil
   110  	}
   111  	return &a
   112  }
   113  
   114  func (a *typedArshalers[Coder]) lookup(fnc func(*Coder, addressableValue, *jsonopts.Struct) error, t reflect.Type) (func(*Coder, addressableValue, *jsonopts.Struct) error, bool) {
   115  	if a == nil {
   116  		return fnc, false
   117  	}
   118  	if v, ok := a.fncCache.Load(t); ok {
   119  		if v == nil {
   120  			return fnc, false
   121  		}
   122  		return v.(func(*Coder, addressableValue, *jsonopts.Struct) error), true
   123  	}
   124  
   125  	// Collect a list of arshalers that can be called for this type.
   126  	// This list may be longer than 1 since some arshalers can be skipped.
   127  	var fncs []func(*Coder, addressableValue, *jsonopts.Struct) error
   128  	for _, fncVal := range a.fncVals {
   129  		if !castableTo(t, fncVal.typ) {
   130  			continue
   131  		}
   132  		fncs = append(fncs, fncVal.fnc)
   133  		if !fncVal.maySkip {
   134  			break // subsequent arshalers will never be called
   135  		}
   136  	}
   137  
   138  	if len(fncs) == 0 {
   139  		a.fncCache.Store(t, nil) // nil to indicate that no funcs found
   140  		return fnc, false
   141  	}
   142  
   143  	// Construct an arshaler that may call every applicable arshaler.
   144  	fncDefault := fnc
   145  	fnc = func(c *Coder, v addressableValue, o *jsonopts.Struct) error {
   146  		for _, fnc := range fncs {
   147  			if err := fnc(c, v, o); !errors.Is(err, errors.ErrUnsupported) {
   148  				return err // may be nil or non-nil
   149  			}
   150  		}
   151  		return fncDefault(c, v, o)
   152  	}
   153  
   154  	// Use the first stored so duplicate work can be garbage collected.
   155  	v, _ := a.fncCache.LoadOrStore(t, fnc)
   156  	return v.(func(*Coder, addressableValue, *jsonopts.Struct) error), true
   157  }
   158  
   159  // MarshalFunc constructs a type-specific marshaler that
   160  // specifies how to marshal values of type T.
   161  // T can be any type except a named pointer.
   162  // The function is always provided with a non-nil pointer value
   163  // if T is an interface or pointer type.
   164  //
   165  // Implementations must follow the requirements of [Marshaler].
   166  //
   167  // Implementations must not retain the value of T.
   168  func MarshalFunc[T any](fn func(T) ([]byte, error)) *Marshalers {
   169  	t := reflect.TypeFor[T]()
   170  	assertCastableTo(t, true)
   171  	typFnc := typedMarshaler{
   172  		typ: t,
   173  		fnc: func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
   174  			v, _ := reflect.TypeAssert[T](va.castTo(t))
   175  			val, err := fn(v)
   176  			if err != nil {
   177  				err = wrapErrUnsupported(err, "marshal function of type func(T) ([]byte, error)")
   178  				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   179  					return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalFunc") // unlike unmarshal, always wrapped
   180  				}
   181  				err = newMarshalErrorBefore(enc, t, err)
   182  				return collapseSemanticErrors(err)
   183  			}
   184  			if err := enc.WriteValue(val); err != nil {
   185  				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   186  					return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalFunc") // unlike unmarshal, always wrapped
   187  				}
   188  				if isSyntacticError(err) {
   189  					err = newMarshalErrorBefore(enc, t, err)
   190  				}
   191  				return err
   192  			}
   193  			return nil
   194  		},
   195  	}
   196  	return &Marshalers{fncVals: []typedMarshaler{typFnc}, fromAny: castableToFromAny(t)}
   197  }
   198  
   199  // MarshalToFunc constructs a type-specific marshaler that
   200  // specifies how to marshal values of type T.
   201  // T can be any type except a named pointer.
   202  // The function is always provided with a non-nil pointer value
   203  // if T is an interface or pointer type.
   204  //
   205  // Implementations must follow the requirements of [MarshalerTo].
   206  //
   207  // Implementations must not retain the pointer to [jsontext.Encoder] or the
   208  // value of T.
   209  func MarshalToFunc[T any](fn func(*jsontext.Encoder, T) error) *Marshalers {
   210  	t := reflect.TypeFor[T]()
   211  	assertCastableTo(t, true)
   212  	typFnc := typedMarshaler{
   213  		typ: t,
   214  		fnc: func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
   215  			xe := export.Encoder(enc)
   216  			prevDepth, prevLength := xe.Tokens.DepthLength()
   217  			xe.Flags.Set(jsonflags.WithinArshalCall | 1)
   218  			v, _ := reflect.TypeAssert[T](va.castTo(t))
   219  			err := fn(enc, v)
   220  			xe.Flags.Set(jsonflags.WithinArshalCall | 0)
   221  			currDepth, currLength := xe.Tokens.DepthLength()
   222  			if err == nil && (prevDepth != currDepth || prevLength+1 != currLength) {
   223  				err = errNonSingularValue
   224  			}
   225  			if err != nil {
   226  				if errors.Is(err, errors.ErrUnsupported) {
   227  					if prevDepth == currDepth && prevLength == currLength {
   228  						return err // forward [errors.ErrUnsupported]
   229  					}
   230  					err = errUnsupportedMutation
   231  				}
   232  				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   233  					return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalToFunc") // unlike unmarshal, always wrapped
   234  				}
   235  				if !export.IsIOError(err) {
   236  					err = newSemanticErrorWithPosition(enc, t, prevDepth, prevLength, err)
   237  				}
   238  				return err
   239  			}
   240  			return nil
   241  		},
   242  		maySkip: true,
   243  	}
   244  	return &Marshalers{fncVals: []typedMarshaler{typFnc}, fromAny: castableToFromAny(t)}
   245  }
   246  
   247  // UnmarshalFunc constructs a type-specific unmarshaler that
   248  // specifies how to unmarshal values of type T.
   249  // T must be an unnamed pointer or an interface type.
   250  // The function is always provided with a non-nil pointer value.
   251  //
   252  // Implementations must follow the requirements of [Unmarshaler].
   253  //
   254  // Implementations must not retain the value of T.
   255  func UnmarshalFunc[T any](fn func([]byte, T) error) *Unmarshalers {
   256  	t := reflect.TypeFor[T]()
   257  	assertCastableTo(t, false)
   258  	typFnc := typedUnmarshaler{
   259  		typ: t,
   260  		fnc: func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
   261  			val, err := dec.ReadValue()
   262  			if err != nil {
   263  				return err // must be a syntactic or I/O error
   264  			}
   265  			v, _ := reflect.TypeAssert[T](va.castTo(t))
   266  			err = fn(val, v)
   267  			if err != nil {
   268  				err = wrapErrUnsupported(err, "unmarshal function of type func([]byte, T) error")
   269  				if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   270  					return err // unlike marshal, never wrapped
   271  				}
   272  				err = newUnmarshalErrorAfter(dec, t, err)
   273  				return collapseSemanticErrors(err)
   274  			}
   275  			return nil
   276  		},
   277  	}
   278  	return &Unmarshalers{fncVals: []typedUnmarshaler{typFnc}, fromAny: castableToFromAny(t)}
   279  }
   280  
   281  // UnmarshalFromFunc constructs a type-specific unmarshaler that
   282  // specifies how to unmarshal values of type T.
   283  // T must be an unnamed pointer or an interface type.
   284  // The function is always provided with a non-nil pointer value.
   285  //
   286  // Implementations must follow the requirements of [UnmarshalerFrom].
   287  //
   288  // Implementations must not retain the pointer to [jsontext.Decoder] or the
   289  // value of T.
   290  func UnmarshalFromFunc[T any](fn func(*jsontext.Decoder, T) error) *Unmarshalers {
   291  	t := reflect.TypeFor[T]()
   292  	assertCastableTo(t, false)
   293  	typFnc := typedUnmarshaler{
   294  		typ: t,
   295  		fnc: func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
   296  			xd := export.Decoder(dec)
   297  			prevDepth, prevLength := xd.Tokens.DepthLength()
   298  			if prevDepth == 1 && xd.AtEOF() {
   299  				return io.EOF // check EOF early to avoid fn reporting an EOF
   300  			}
   301  			xd.Flags.Set(jsonflags.WithinArshalCall | 1)
   302  			v, _ := reflect.TypeAssert[T](va.castTo(t))
   303  			err := fn(dec, v)
   304  			xd.Flags.Set(jsonflags.WithinArshalCall | 0)
   305  			currDepth, currLength := xd.Tokens.DepthLength()
   306  			if err == nil && (prevDepth != currDepth || prevLength+1 != currLength) {
   307  				err = errNonSingularValue
   308  			}
   309  			if err != nil {
   310  				if errors.Is(err, errors.ErrUnsupported) {
   311  					if prevDepth == currDepth && prevLength == currLength {
   312  						return err // forward [errors.ErrUnsupported]
   313  					}
   314  					err = errUnsupportedMutation
   315  				}
   316  				if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   317  					if err2 := xd.SkipUntil(prevDepth, prevLength+1); err2 != nil {
   318  						return err2
   319  					}
   320  					return err // unlike marshal, never wrapped
   321  				}
   322  				if !isSyntacticError(err) && !export.IsIOError(err) {
   323  					err = newSemanticErrorWithPosition(dec, t, prevDepth, prevLength, err)
   324  				}
   325  				return err
   326  			}
   327  			return nil
   328  		},
   329  		maySkip: true,
   330  	}
   331  	return &Unmarshalers{fncVals: []typedUnmarshaler{typFnc}, fromAny: castableToFromAny(t)}
   332  }
   333  
   334  // assertCastableTo asserts that "to" is a valid type to be casted to.
   335  // These are the Go types that type-specific arshalers may operate upon.
   336  //
   337  // Let AllTypes be the universal set of all possible Go types.
   338  // This function generally asserts that:
   339  //
   340  //	len([from for from in AllTypes if castableTo(from, to)]) > 0
   341  //
   342  // otherwise it panics.
   343  //
   344  // As a special-case if marshal is false, then we forbid any non-pointer or
   345  // non-interface type since it is almost always a bug trying to unmarshal
   346  // into something where the end-user caller did not pass in an addressable value
   347  // since they will not observe the mutations.
   348  func assertCastableTo(to reflect.Type, marshal bool) {
   349  	switch to.Kind() {
   350  	case reflect.Interface:
   351  		return
   352  	case reflect.Pointer:
   353  		// Only allow unnamed pointers to be consistent with the fact that
   354  		// taking the address of a value produces an unnamed pointer type.
   355  		if to.Name() == "" {
   356  			return
   357  		}
   358  	default:
   359  		// Technically, non-pointer types are permissible for unmarshal.
   360  		// However, they are often a bug since the receiver would be immutable.
   361  		// Thus, only allow them for marshaling.
   362  		if marshal {
   363  			return
   364  		}
   365  	}
   366  	if marshal {
   367  		panic(fmt.Sprintf("input type %v must be an interface type, an unnamed pointer type, or a non-pointer type", to))
   368  	} else {
   369  		panic(fmt.Sprintf("input type %v must be an interface type or an unnamed pointer type", to))
   370  	}
   371  }
   372  
   373  // castableTo checks whether values of type "from" can be casted to type "to".
   374  // Nil pointer or interface "from" values are never considered castable.
   375  //
   376  // This function must be kept in sync with addressableValue.castTo.
   377  func castableTo(from, to reflect.Type) bool {
   378  	switch to.Kind() {
   379  	case reflect.Interface:
   380  		// TODO: This breaks when ordinary interfaces can have type sets
   381  		// since interfaces now exist where only the value form of a type (T)
   382  		// implements the interface, but not the pointer variant (*T).
   383  		// See https://go.dev/issue/45346.
   384  		return reflect.PointerTo(from).Implements(to)
   385  	case reflect.Pointer:
   386  		// Common case for unmarshaling.
   387  		// From must be a concrete or interface type.
   388  		return reflect.PointerTo(from) == to
   389  	default:
   390  		// Common case for marshaling.
   391  		// From must be a concrete type.
   392  		return from == to
   393  	}
   394  }
   395  
   396  // castTo casts va to the specified type.
   397  // If the type is an interface, then the underlying type will always
   398  // be a non-nil pointer to a concrete type.
   399  //
   400  // Requirement: castableTo(va.Type(), to) must hold.
   401  func (va addressableValue) castTo(to reflect.Type) reflect.Value {
   402  	switch to.Kind() {
   403  	case reflect.Interface:
   404  		return va.Addr().Convert(to)
   405  	case reflect.Pointer:
   406  		return va.Addr()
   407  	default:
   408  		return va.Value
   409  	}
   410  }
   411  
   412  // castableToFromAny reports whether "to" can be casted to from any
   413  // of the dynamic types used to represent arbitrary JSON.
   414  func castableToFromAny(to reflect.Type) bool {
   415  	for _, from := range []reflect.Type{anyType, boolType, stringType, float64Type, mapStringAnyType, sliceAnyType} {
   416  		if castableTo(from, to) {
   417  			return true
   418  		}
   419  	}
   420  	return false
   421  }
   422  

View as plain text