k8s.io/kube-openapi@v0.0.0-20240228011516-70dd3763d340/pkg/internal/third_party/go-json-experiment/json/arshal.go (about)

     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  package json
     6  
     7  import (
     8  	"errors"
     9  	"io"
    10  	"reflect"
    11  	"sync"
    12  )
    13  
    14  // MarshalOptions configures how Go data is serialized as JSON data.
    15  // The zero value is equivalent to the default marshal settings.
    16  type MarshalOptions struct {
    17  	requireKeyedLiterals
    18  	nonComparable
    19  
    20  	// Marshalers is a list of type-specific marshalers to use.
    21  	Marshalers *Marshalers
    22  
    23  	// StringifyNumbers specifies that numeric Go types should be serialized
    24  	// as a JSON string containing the equivalent JSON number value.
    25  	//
    26  	// According to RFC 8259, section 6, a JSON implementation may choose to
    27  	// limit the representation of a JSON number to an IEEE 754 binary64 value.
    28  	// This may cause decoders to lose precision for int64 and uint64 types.
    29  	// Escaping JSON numbers as a JSON string preserves the exact precision.
    30  	StringifyNumbers bool
    31  
    32  	// DiscardUnknownMembers specifies that marshaling should ignore any
    33  	// JSON object members stored in Go struct fields dedicated to storing
    34  	// unknown JSON object members.
    35  	DiscardUnknownMembers bool
    36  
    37  	// Deterministic specifies that the same input value will be serialized
    38  	// as the exact same output bytes. Different processes of
    39  	// the same program will serialize equal values to the same bytes,
    40  	// but different versions of the same program are not guaranteed
    41  	// to produce the exact same sequence of bytes.
    42  	Deterministic bool
    43  
    44  	// formatDepth is the depth at which we respect the format flag.
    45  	formatDepth int
    46  	// format is custom formatting for the value at the specified depth.
    47  	format string
    48  }
    49  
    50  // Marshal serializes a Go value as a []byte with default options.
    51  // It is a thin wrapper over MarshalOptions.Marshal.
    52  func Marshal(in any) (out []byte, err error) {
    53  	return MarshalOptions{}.Marshal(EncodeOptions{}, in)
    54  }
    55  
    56  // MarshalFull serializes a Go value into an io.Writer with default options.
    57  // It is a thin wrapper over MarshalOptions.MarshalFull.
    58  func MarshalFull(out io.Writer, in any) error {
    59  	return MarshalOptions{}.MarshalFull(EncodeOptions{}, out, in)
    60  }
    61  
    62  // Marshal serializes a Go value as a []byte according to the provided
    63  // marshal and encode options. It does not terminate the output with a newline.
    64  // See MarshalNext for details about the conversion of a Go value into JSON.
    65  func (mo MarshalOptions) Marshal(eo EncodeOptions, in any) (out []byte, err error) {
    66  	enc := getBufferedEncoder(eo)
    67  	defer putBufferedEncoder(enc)
    68  	enc.options.omitTopLevelNewline = true
    69  	err = mo.MarshalNext(enc, in)
    70  	// TODO(https://go.dev/issue/45038): Use bytes.Clone.
    71  	return append([]byte(nil), enc.buf...), err
    72  }
    73  
    74  // MarshalFull serializes a Go value into an io.Writer according to the provided
    75  // marshal and encode options. It does not terminate the output with a newline.
    76  // See MarshalNext for details about the conversion of a Go value into JSON.
    77  func (mo MarshalOptions) MarshalFull(eo EncodeOptions, out io.Writer, in any) error {
    78  	enc := getStreamingEncoder(out, eo)
    79  	defer putStreamingEncoder(enc)
    80  	enc.options.omitTopLevelNewline = true
    81  	err := mo.MarshalNext(enc, in)
    82  	return err
    83  }
    84  
    85  // MarshalNext encodes a Go value as the next JSON value according to
    86  // the provided marshal options.
    87  //
    88  // Type-specific marshal functions and methods take precedence
    89  // over the default representation of a value.
    90  // Functions or methods that operate on *T are only called when encoding
    91  // a value of type T (by taking its address) or a non-nil value of *T.
    92  // MarshalNext ensures that a value is always addressable
    93  // (by boxing it on the heap if necessary) so that
    94  // these functions and methods can be consistently called. For performance,
    95  // it is recommended that MarshalNext be passed a non-nil pointer to the value.
    96  //
    97  // The input value is encoded as JSON according the following rules:
    98  //
    99  //   - If any type-specific functions in MarshalOptions.Marshalers match
   100  //     the value type, then those functions are called to encode the value.
   101  //     If all applicable functions return SkipFunc,
   102  //     then the value is encoded according to subsequent rules.
   103  //
   104  //   - If the value type implements MarshalerV2,
   105  //     then the MarshalNextJSON method is called to encode the value.
   106  //
   107  //   - If the value type implements MarshalerV1,
   108  //     then the MarshalJSON method is called to encode the value.
   109  //
   110  //   - If the value type implements encoding.TextMarshaler,
   111  //     then the MarshalText method is called to encode the value and
   112  //     subsequently encode its result as a JSON string.
   113  //
   114  //   - Otherwise, the value is encoded according to the value's type
   115  //     as described in detail below.
   116  //
   117  // Most Go types have a default JSON representation.
   118  // Certain types support specialized formatting according to
   119  // a format flag optionally specified in the Go struct tag
   120  // for the struct field that contains the current value
   121  // (see the “JSON Representation of Go structs” section for more details).
   122  //
   123  // The representation of each type is as follows:
   124  //
   125  //   - A Go boolean is encoded as a JSON boolean (e.g., true or false).
   126  //     It does not support any custom format flags.
   127  //
   128  //   - A Go string is encoded as a JSON string.
   129  //     It does not support any custom format flags.
   130  //
   131  //   - A Go []byte or [N]byte is encoded as a JSON string containing
   132  //     the binary value encoded using RFC 4648.
   133  //     If the format is "base64" or unspecified, then this uses RFC 4648, section 4.
   134  //     If the format is "base64url", then this uses RFC 4648, section 5.
   135  //     If the format is "base32", then this uses RFC 4648, section 6.
   136  //     If the format is "base32hex", then this uses RFC 4648, section 7.
   137  //     If the format is "base16" or "hex", then this uses RFC 4648, section 8.
   138  //     If the format is "array", then the bytes value is encoded as a JSON array
   139  //     where each byte is recursively JSON-encoded as each JSON array element.
   140  //
   141  //   - A Go integer is encoded as a JSON number without fractions or exponents.
   142  //     If MarshalOptions.StringifyNumbers is specified, then the JSON number is
   143  //     encoded within a JSON string. It does not support any custom format
   144  //     flags.
   145  //
   146  //   - A Go float is encoded as a JSON number.
   147  //     If MarshalOptions.StringifyNumbers is specified,
   148  //     then the JSON number is encoded within a JSON string.
   149  //     If the format is "nonfinite", then NaN, +Inf, and -Inf are encoded as
   150  //     the JSON strings "NaN", "Infinity", and "-Infinity", respectively.
   151  //     Otherwise, the presence of non-finite numbers results in a SemanticError.
   152  //
   153  //   - A Go map is encoded as a JSON object, where each Go map key and value
   154  //     is recursively encoded as a name and value pair in the JSON object.
   155  //     The Go map key must encode as a JSON string, otherwise this results
   156  //     in a SemanticError. When encoding keys, MarshalOptions.StringifyNumbers
   157  //     is automatically applied so that numeric keys encode as JSON strings.
   158  //     The Go map is traversed in a non-deterministic order.
   159  //     For deterministic encoding, consider using RawValue.Canonicalize.
   160  //     If the format is "emitnull", then a nil map is encoded as a JSON null.
   161  //     Otherwise by default, a nil map is encoded as an empty JSON object.
   162  //
   163  //   - A Go struct is encoded as a JSON object.
   164  //     See the “JSON Representation of Go structs” section
   165  //     in the package-level documentation for more details.
   166  //
   167  //   - A Go slice is encoded as a JSON array, where each Go slice element
   168  //     is recursively JSON-encoded as the elements of the JSON array.
   169  //     If the format is "emitnull", then a nil slice is encoded as a JSON null.
   170  //     Otherwise by default, a nil slice is encoded as an empty JSON array.
   171  //
   172  //   - A Go array is encoded as a JSON array, where each Go array element
   173  //     is recursively JSON-encoded as the elements of the JSON array.
   174  //     The JSON array length is always identical to the Go array length.
   175  //     It does not support any custom format flags.
   176  //
   177  //   - A Go pointer is encoded as a JSON null if nil, otherwise it is
   178  //     the recursively JSON-encoded representation of the underlying value.
   179  //     Format flags are forwarded to the encoding of the underlying value.
   180  //
   181  //   - A Go interface is encoded as a JSON null if nil, otherwise it is
   182  //     the recursively JSON-encoded representation of the underlying value.
   183  //     It does not support any custom format flags.
   184  //
   185  //   - A Go time.Time is encoded as a JSON string containing the timestamp
   186  //     formatted in RFC 3339 with nanosecond resolution.
   187  //     If the format matches one of the format constants declared
   188  //     in the time package (e.g., RFC1123), then that format is used.
   189  //     Otherwise, the format is used as-is with time.Time.Format if non-empty.
   190  //
   191  //   - A Go time.Duration is encoded as a JSON string containing the duration
   192  //     formatted according to time.Duration.String.
   193  //     If the format is "nanos", it is encoded as a JSON number
   194  //     containing the number of nanoseconds in the duration.
   195  //
   196  //   - All other Go types (e.g., complex numbers, channels, and functions)
   197  //     have no default representation and result in a SemanticError.
   198  //
   199  // JSON cannot represent cyclic data structures and
   200  // MarshalNext does not handle them.
   201  // Passing cyclic structures will result in an error.
   202  func (mo MarshalOptions) MarshalNext(out *Encoder, in any) error {
   203  	v := reflect.ValueOf(in)
   204  	if !v.IsValid() || (v.Kind() == reflect.Pointer && v.IsNil()) {
   205  		return out.WriteToken(Null)
   206  	}
   207  	// Shallow copy non-pointer values to obtain an addressable value.
   208  	// It is beneficial to performance to always pass pointers to avoid this.
   209  	if v.Kind() != reflect.Pointer {
   210  		v2 := reflect.New(v.Type())
   211  		v2.Elem().Set(v)
   212  		v = v2
   213  	}
   214  	va := addressableValue{v.Elem()} // dereferenced pointer is always addressable
   215  	t := va.Type()
   216  
   217  	// Lookup and call the marshal function for this type.
   218  	marshal := lookupArshaler(t).marshal
   219  	if mo.Marshalers != nil {
   220  		marshal, _ = mo.Marshalers.lookup(marshal, t)
   221  	}
   222  	if err := marshal(mo, out, va); err != nil {
   223  		if !out.options.AllowDuplicateNames {
   224  			out.tokens.invalidateDisabledNamespaces()
   225  		}
   226  		return err
   227  	}
   228  	return nil
   229  }
   230  
   231  // UnmarshalOptions configures how JSON data is deserialized as Go data.
   232  // The zero value is equivalent to the default unmarshal settings.
   233  type UnmarshalOptions struct {
   234  	requireKeyedLiterals
   235  	nonComparable
   236  
   237  	// Unmarshalers is a list of type-specific unmarshalers to use.
   238  	Unmarshalers *Unmarshalers
   239  
   240  	// StringifyNumbers specifies that numeric Go types can be deserialized
   241  	// from either a JSON number or a JSON string containing a JSON number
   242  	// without any surrounding whitespace.
   243  	StringifyNumbers bool
   244  
   245  	// RejectUnknownMembers specifies that unknown members should be rejected
   246  	// when unmarshaling a JSON object, regardless of whether there is a field
   247  	// to store unknown members.
   248  	RejectUnknownMembers bool
   249  
   250  	// formatDepth is the depth at which we respect the format flag.
   251  	formatDepth int
   252  	// format is custom formatting for the value at the specified depth.
   253  	format string
   254  }
   255  
   256  // Unmarshal deserializes a Go value from a []byte with default options.
   257  // It is a thin wrapper over UnmarshalOptions.Unmarshal.
   258  func Unmarshal(in []byte, out any) error {
   259  	return UnmarshalOptions{}.Unmarshal(DecodeOptions{}, in, out)
   260  }
   261  
   262  // UnmarshalFull deserializes a Go value from an io.Reader with default options.
   263  // It is a thin wrapper over UnmarshalOptions.UnmarshalFull.
   264  func UnmarshalFull(in io.Reader, out any) error {
   265  	return UnmarshalOptions{}.UnmarshalFull(DecodeOptions{}, in, out)
   266  }
   267  
   268  // Unmarshal deserializes a Go value from a []byte according to the
   269  // provided unmarshal and decode options. The output must be a non-nil pointer.
   270  // The input must be a single JSON value with optional whitespace interspersed.
   271  // See UnmarshalNext for details about the conversion of JSON into a Go value.
   272  func (uo UnmarshalOptions) Unmarshal(do DecodeOptions, in []byte, out any) error {
   273  	dec := getBufferedDecoder(in, do)
   274  	defer putBufferedDecoder(dec)
   275  	return uo.unmarshalFull(dec, out)
   276  }
   277  
   278  // UnmarshalFull deserializes a Go value from an io.Reader according to the
   279  // provided unmarshal and decode options. The output must be a non-nil pointer.
   280  // The input must be a single JSON value with optional whitespace interspersed.
   281  // It consumes the entirety of io.Reader until io.EOF is encountered.
   282  // See UnmarshalNext for details about the conversion of JSON into a Go value.
   283  func (uo UnmarshalOptions) UnmarshalFull(do DecodeOptions, in io.Reader, out any) error {
   284  	dec := getStreamingDecoder(in, do)
   285  	defer putStreamingDecoder(dec)
   286  	return uo.unmarshalFull(dec, out)
   287  }
   288  func (uo UnmarshalOptions) unmarshalFull(in *Decoder, out any) error {
   289  	switch err := uo.UnmarshalNext(in, out); err {
   290  	case nil:
   291  		return in.checkEOF()
   292  	case io.EOF:
   293  		return io.ErrUnexpectedEOF
   294  	default:
   295  		return err
   296  	}
   297  }
   298  
   299  // UnmarshalNext decodes the next JSON value into a Go value according to
   300  // the provided unmarshal options. The output must be a non-nil pointer.
   301  //
   302  // Type-specific unmarshal functions and methods take precedence
   303  // over the default representation of a value.
   304  // Functions or methods that operate on *T are only called when decoding
   305  // a value of type T (by taking its address) or a non-nil value of *T.
   306  // UnmarshalNext ensures that a value is always addressable
   307  // (by boxing it on the heap if necessary) so that
   308  // these functions and methods can be consistently called.
   309  //
   310  // The input is decoded into the output according the following rules:
   311  //
   312  //   - If any type-specific functions in UnmarshalOptions.Unmarshalers match
   313  //     the value type, then those functions are called to decode the JSON
   314  //     value. If all applicable functions return SkipFunc,
   315  //     then the input is decoded according to subsequent rules.
   316  //
   317  //   - If the value type implements UnmarshalerV2,
   318  //     then the UnmarshalNextJSON method is called to decode the JSON value.
   319  //
   320  //   - If the value type implements UnmarshalerV1,
   321  //     then the UnmarshalJSON method is called to decode the JSON value.
   322  //
   323  //   - If the value type implements encoding.TextUnmarshaler,
   324  //     then the input is decoded as a JSON string and
   325  //     the UnmarshalText method is called with the decoded string value.
   326  //     This fails with a SemanticError if the input is not a JSON string.
   327  //
   328  //   - Otherwise, the JSON value is decoded according to the value's type
   329  //     as described in detail below.
   330  //
   331  // Most Go types have a default JSON representation.
   332  // Certain types support specialized formatting according to
   333  // a format flag optionally specified in the Go struct tag
   334  // for the struct field that contains the current value
   335  // (see the “JSON Representation of Go structs” section for more details).
   336  // A JSON null may be decoded into every supported Go value where
   337  // it is equivalent to storing the zero value of the Go value.
   338  // If the input JSON kind is not handled by the current Go value type,
   339  // then this fails with a SemanticError. Unless otherwise specified,
   340  // the decoded value replaces any pre-existing value.
   341  //
   342  // The representation of each type is as follows:
   343  //
   344  //   - A Go boolean is decoded from a JSON boolean (e.g., true or false).
   345  //     It does not support any custom format flags.
   346  //
   347  //   - A Go string is decoded from a JSON string.
   348  //     It does not support any custom format flags.
   349  //
   350  //   - A Go []byte or [N]byte is decoded from a JSON string
   351  //     containing the binary value encoded using RFC 4648.
   352  //     If the format is "base64" or unspecified, then this uses RFC 4648, section 4.
   353  //     If the format is "base64url", then this uses RFC 4648, section 5.
   354  //     If the format is "base32", then this uses RFC 4648, section 6.
   355  //     If the format is "base32hex", then this uses RFC 4648, section 7.
   356  //     If the format is "base16" or "hex", then this uses RFC 4648, section 8.
   357  //     If the format is "array", then the Go slice or array is decoded from a
   358  //     JSON array where each JSON element is recursively decoded for each byte.
   359  //     When decoding into a non-nil []byte, the slice length is reset to zero
   360  //     and the decoded input is appended to it.
   361  //     When decoding into a [N]byte, the input must decode to exactly N bytes,
   362  //     otherwise it fails with a SemanticError.
   363  //
   364  //   - A Go integer is decoded from a JSON number.
   365  //     It may also be decoded from a JSON string containing a JSON number
   366  //     if UnmarshalOptions.StringifyNumbers is specified.
   367  //     It fails with a SemanticError if the JSON number
   368  //     has a fractional or exponent component.
   369  //     It also fails if it overflows the representation of the Go integer type.
   370  //     It does not support any custom format flags.
   371  //
   372  //   - A Go float is decoded from a JSON number.
   373  //     It may also be decoded from a JSON string containing a JSON number
   374  //     if UnmarshalOptions.StringifyNumbers is specified.
   375  //     The JSON number is parsed as the closest representable Go float value.
   376  //     If the format is "nonfinite", then the JSON strings
   377  //     "NaN", "Infinity", and "-Infinity" are decoded as NaN, +Inf, and -Inf.
   378  //     Otherwise, the presence of such strings results in a SemanticError.
   379  //
   380  //   - A Go map is decoded from a JSON object,
   381  //     where each JSON object name and value pair is recursively decoded
   382  //     as the Go map key and value. When decoding keys,
   383  //     UnmarshalOptions.StringifyNumbers is automatically applied so that
   384  //     numeric keys can decode from JSON strings. Maps are not cleared.
   385  //     If the Go map is nil, then a new map is allocated to decode into.
   386  //     If the decoded key matches an existing Go map entry, the entry value
   387  //     is reused by decoding the JSON object value into it.
   388  //     The only supported format is "emitnull" and has no effect when decoding.
   389  //
   390  //   - A Go struct is decoded from a JSON object.
   391  //     See the “JSON Representation of Go structs” section
   392  //     in the package-level documentation for more details.
   393  //
   394  //   - A Go slice is decoded from a JSON array, where each JSON element
   395  //     is recursively decoded and appended to the Go slice.
   396  //     Before appending into a Go slice, a new slice is allocated if it is nil,
   397  //     otherwise the slice length is reset to zero.
   398  //     The only supported format is "emitnull" and has no effect when decoding.
   399  //
   400  //   - A Go array is decoded from a JSON array, where each JSON array element
   401  //     is recursively decoded as each corresponding Go array element.
   402  //     Each Go array element is zeroed before decoding into it.
   403  //     It fails with a SemanticError if the JSON array does not contain
   404  //     the exact same number of elements as the Go array.
   405  //     It does not support any custom format flags.
   406  //
   407  //   - A Go pointer is decoded based on the JSON kind and underlying Go type.
   408  //     If the input is a JSON null, then this stores a nil pointer.
   409  //     Otherwise, it allocates a new underlying value if the pointer is nil,
   410  //     and recursively JSON decodes into the underlying value.
   411  //     Format flags are forwarded to the decoding of the underlying type.
   412  //
   413  //   - A Go interface is decoded based on the JSON kind and underlying Go type.
   414  //     If the input is a JSON null, then this stores a nil interface value.
   415  //     Otherwise, a nil interface value of an empty interface type is initialized
   416  //     with a zero Go bool, string, float64, map[string]any, or []any if the
   417  //     input is a JSON boolean, string, number, object, or array, respectively.
   418  //     If the interface value is still nil, then this fails with a SemanticError
   419  //     since decoding could not determine an appropriate Go type to decode into.
   420  //     For example, unmarshaling into a nil io.Reader fails since
   421  //     there is no concrete type to populate the interface value with.
   422  //     Otherwise an underlying value exists and it recursively decodes
   423  //     the JSON input into it. It does not support any custom format flags.
   424  //
   425  //   - A Go time.Time is decoded from a JSON string containing the time
   426  //     formatted in RFC 3339 with nanosecond resolution.
   427  //     If the format matches one of the format constants declared in
   428  //     the time package (e.g., RFC1123), then that format is used for parsing.
   429  //     Otherwise, the format is used as-is with time.Time.Parse if non-empty.
   430  //
   431  //   - A Go time.Duration is decoded from a JSON string by
   432  //     passing the decoded string to time.ParseDuration.
   433  //     If the format is "nanos", it is instead decoded from a JSON number
   434  //     containing the number of nanoseconds in the duration.
   435  //
   436  //   - All other Go types (e.g., complex numbers, channels, and functions)
   437  //     have no default representation and result in a SemanticError.
   438  //
   439  // In general, unmarshaling follows merge semantics (similar to RFC 7396)
   440  // where the decoded Go value replaces the destination value
   441  // for any JSON kind other than an object.
   442  // For JSON objects, the input object is merged into the destination value
   443  // where matching object members recursively apply merge semantics.
   444  func (uo UnmarshalOptions) UnmarshalNext(in *Decoder, out any) error {
   445  	v := reflect.ValueOf(out)
   446  	if !v.IsValid() || v.Kind() != reflect.Pointer || v.IsNil() {
   447  		var t reflect.Type
   448  		if v.IsValid() {
   449  			t = v.Type()
   450  			if t.Kind() == reflect.Pointer {
   451  				t = t.Elem()
   452  			}
   453  		}
   454  		err := errors.New("value must be passed as a non-nil pointer reference")
   455  		return &SemanticError{action: "unmarshal", GoType: t, Err: err}
   456  	}
   457  	va := addressableValue{v.Elem()} // dereferenced pointer is always addressable
   458  	t := va.Type()
   459  
   460  	// Lookup and call the unmarshal function for this type.
   461  	unmarshal := lookupArshaler(t).unmarshal
   462  	if uo.Unmarshalers != nil {
   463  		unmarshal, _ = uo.Unmarshalers.lookup(unmarshal, t)
   464  	}
   465  	if err := unmarshal(uo, in, va); err != nil {
   466  		if !in.options.AllowDuplicateNames {
   467  			in.tokens.invalidateDisabledNamespaces()
   468  		}
   469  		return err
   470  	}
   471  	return nil
   472  }
   473  
   474  // addressableValue is a reflect.Value that is guaranteed to be addressable
   475  // such that calling the Addr and Set methods do not panic.
   476  //
   477  // There is no compile magic that enforces this property,
   478  // but rather the need to construct this type makes it easier to examine each
   479  // construction site to ensure that this property is upheld.
   480  type addressableValue struct{ reflect.Value }
   481  
   482  // newAddressableValue constructs a new addressable value of type t.
   483  func newAddressableValue(t reflect.Type) addressableValue {
   484  	return addressableValue{reflect.New(t).Elem()}
   485  }
   486  
   487  // All marshal and unmarshal behavior is implemented using these signatures.
   488  type (
   489  	marshaler   = func(MarshalOptions, *Encoder, addressableValue) error
   490  	unmarshaler = func(UnmarshalOptions, *Decoder, addressableValue) error
   491  )
   492  
   493  type arshaler struct {
   494  	marshal    marshaler
   495  	unmarshal  unmarshaler
   496  	nonDefault bool
   497  }
   498  
   499  var lookupArshalerCache sync.Map // map[reflect.Type]*arshaler
   500  
   501  func lookupArshaler(t reflect.Type) *arshaler {
   502  	if v, ok := lookupArshalerCache.Load(t); ok {
   503  		return v.(*arshaler)
   504  	}
   505  
   506  	fncs := makeDefaultArshaler(t)
   507  	fncs = makeMethodArshaler(fncs, t)
   508  	fncs = makeTimeArshaler(fncs, t)
   509  
   510  	// Use the last stored so that duplicate arshalers can be garbage collected.
   511  	v, _ := lookupArshalerCache.LoadOrStore(t, fncs)
   512  	return v.(*arshaler)
   513  }