Files
kubevpn/vendor/github.com/go-json-experiment/json/arshal_methods.go
naison d141ec869b fix: fix dns on linux (#336)
* fix: fix dns on linux

* feat: detect run in Github action or not to setup DNS
2024-10-09 19:17:50 +08:00

260 lines
11 KiB
Go

// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package json
import (
"encoding"
"errors"
"reflect"
"github.com/go-json-experiment/json/internal/jsonflags"
"github.com/go-json-experiment/json/internal/jsonopts"
"github.com/go-json-experiment/json/internal/jsonwire"
"github.com/go-json-experiment/json/jsontext"
)
// Interfaces for custom serialization.
var (
jsonMarshalerV1Type = reflect.TypeOf((*MarshalerV1)(nil)).Elem()
jsonMarshalerV2Type = reflect.TypeOf((*MarshalerV2)(nil)).Elem()
jsonUnmarshalerV1Type = reflect.TypeOf((*UnmarshalerV1)(nil)).Elem()
jsonUnmarshalerV2Type = reflect.TypeOf((*UnmarshalerV2)(nil)).Elem()
textAppenderType = reflect.TypeOf((*encodingTextAppender)(nil)).Elem()
textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
// TODO(https://go.dev/issue/62384): Use encoding.TextAppender instead of this hack.
// This exists for now to provide performance benefits to netip types.
// There is no semantic difference with this change.
appenderToType = reflect.TypeOf((*interface{ AppendTo([]byte) []byte })(nil)).Elem()
)
// TODO(https://go.dev/issue/62384): Use encoding.TextAppender instead
// and document public support for this method in json.Marshal.
type encodingTextAppender interface {
AppendText(b []byte) ([]byte, error)
}
// MarshalerV1 is implemented by types that can marshal themselves.
// It is recommended that types implement [MarshalerV2] unless the implementation
// is trying to avoid a hard dependency on the "jsontext" package.
//
// It is recommended that implementations return a buffer that is safe
// for the caller to retain and potentially mutate.
type MarshalerV1 interface {
MarshalJSON() ([]byte, error)
}
// MarshalerV2 is implemented by types that can marshal themselves.
// It is recommended that types implement MarshalerV2 instead of [MarshalerV1]
// since this is both more performant and flexible.
// If a type implements both MarshalerV1 and MarshalerV2,
// then MarshalerV2 takes precedence. In such a case, both implementations
// should aim to have equivalent behavior for the default marshal options.
//
// The implementation must write only one JSON value to the Encoder and
// must not retain the pointer to [jsontext.Encoder] or the [Options] value.
type MarshalerV2 interface {
MarshalJSONV2(*jsontext.Encoder, Options) error
// TODO: Should users call the MarshalEncode function or
// should/can they call this method directly? Does it matter?
}
// UnmarshalerV1 is implemented by types that can unmarshal themselves.
// It is recommended that types implement [UnmarshalerV2] unless the implementation
// is trying to avoid a hard dependency on the "jsontext" package.
//
// The input can be assumed to be a valid encoding of a JSON value
// if called from unmarshal functionality in this package.
// UnmarshalJSON must copy the JSON data if it is retained after returning.
// It is recommended that UnmarshalJSON implement merge semantics when
// unmarshaling into a pre-populated value.
//
// Implementations must not retain or mutate the input []byte.
type UnmarshalerV1 interface {
UnmarshalJSON([]byte) error
}
// UnmarshalerV2 is implemented by types that can unmarshal themselves.
// It is recommended that types implement UnmarshalerV2 instead of [UnmarshalerV1]
// since this is both more performant and flexible.
// If a type implements both UnmarshalerV1 and UnmarshalerV2,
// then UnmarshalerV2 takes precedence. In such a case, both implementations
// should aim to have equivalent behavior for the default unmarshal options.
//
// The implementation must read only one JSON value from the Decoder.
// It is recommended that UnmarshalJSONV2 implement merge semantics when
// unmarshaling into a pre-populated value.
//
// Implementations must not retain the pointer to [jsontext.Decoder] or
// the [Options] value.
type UnmarshalerV2 interface {
UnmarshalJSONV2(*jsontext.Decoder, Options) error
// TODO: Should users call the UnmarshalDecode function or
// should/can they call this method directly? Does it matter?
}
func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
// Avoid injecting method arshaler on the pointer or interface version
// to avoid ever calling the method on a nil pointer or interface receiver.
// Let it be injected on the value receiver (which is always addressable).
if t.Kind() == reflect.Pointer || t.Kind() == reflect.Interface {
return fncs
}
// Handle custom marshaler.
switch which := implementsWhich(t, jsonMarshalerV2Type, jsonMarshalerV1Type, textAppenderType, textMarshalerType); which {
case jsonMarshalerV2Type:
fncs.nonDefault = true
fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
xe := export.Encoder(enc)
prevDepth, prevLength := xe.Tokens.DepthLength()
xe.Flags.Set(jsonflags.WithinArshalCall | 1)
err := va.Addr().Interface().(MarshalerV2).MarshalJSONV2(enc, mo)
xe.Flags.Set(jsonflags.WithinArshalCall | 0)
currDepth, currLength := xe.Tokens.DepthLength()
if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
err = errors.New("must write exactly one JSON value")
}
if err != nil {
err = wrapSkipFunc(err, "marshal method")
// TODO: Avoid wrapping semantic or I/O errors.
return &SemanticError{action: "marshal", GoType: t, Err: err}
}
return nil
}
case jsonMarshalerV1Type:
fncs.nonDefault = true
fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
marshaler := va.Addr().Interface().(MarshalerV1)
val, err := marshaler.MarshalJSON()
if err != nil {
err = wrapSkipFunc(err, "marshal method")
// TODO: Avoid wrapping semantic errors.
return &SemanticError{action: "marshal", GoType: t, Err: err}
}
if err := enc.WriteValue(val); err != nil {
// TODO: Avoid wrapping semantic or I/O errors.
return &SemanticError{action: "marshal", JSONKind: jsontext.Value(val).Kind(), GoType: t, Err: err}
}
return nil
}
case textAppenderType:
fncs.nonDefault = true
fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) (err error) {
appender := va.Addr().Interface().(encodingTextAppender)
if err := export.Encoder(enc).AppendRaw('"', false, appender.AppendText); err != nil {
// TODO: Avoid wrapping semantic, syntactic, or I/O errors.
err = wrapSkipFunc(err, "append method")
return &SemanticError{action: "marshal", JSONKind: '"', GoType: t, Err: err}
}
return nil
}
case textMarshalerType:
fncs.nonDefault = true
fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
marshaler := va.Addr().Interface().(encoding.TextMarshaler)
if err := export.Encoder(enc).AppendRaw('"', false, func(b []byte) ([]byte, error) {
b2, err := marshaler.MarshalText()
return append(b, b2...), err
}); err != nil {
// TODO: Avoid wrapping semantic, syntactic, or I/O errors.
err = wrapSkipFunc(err, "marshal method")
return &SemanticError{action: "marshal", JSONKind: '"', GoType: t, Err: err}
}
return nil
}
// TODO(https://go.dev/issue/62384): Rely on encoding.TextAppender instead.
if implementsWhich(t, appenderToType) != nil && t.PkgPath() == "net/netip" {
fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
appender := va.Addr().Interface().(interface{ AppendTo([]byte) []byte })
if err := export.Encoder(enc).AppendRaw('"', false, func(b []byte) ([]byte, error) {
return appender.AppendTo(b), nil
}); err != nil {
// TODO: Avoid wrapping semantic, syntactic, or I/O errors.
err = wrapSkipFunc(err, "append method")
return &SemanticError{action: "marshal", JSONKind: '"', GoType: t, Err: err}
}
return nil
}
}
}
// Handle custom unmarshaler.
switch which := implementsWhich(t, jsonUnmarshalerV2Type, jsonUnmarshalerV1Type, textUnmarshalerType); which {
case jsonUnmarshalerV2Type:
fncs.nonDefault = true
fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
xd := export.Decoder(dec)
prevDepth, prevLength := xd.Tokens.DepthLength()
xd.Flags.Set(jsonflags.WithinArshalCall | 1)
err := va.Addr().Interface().(UnmarshalerV2).UnmarshalJSONV2(dec, uo)
xd.Flags.Set(jsonflags.WithinArshalCall | 0)
currDepth, currLength := xd.Tokens.DepthLength()
if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
err = errors.New("must read exactly one JSON value")
}
if err != nil {
err = wrapSkipFunc(err, "unmarshal method")
// TODO: Avoid wrapping semantic, syntactic, or I/O errors.
return &SemanticError{action: "unmarshal", GoType: t, Err: err}
}
return nil
}
case jsonUnmarshalerV1Type:
fncs.nonDefault = true
fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
val, err := dec.ReadValue()
if err != nil {
return err // must be a syntactic or I/O error
}
unmarshaler := va.Addr().Interface().(UnmarshalerV1)
if err := unmarshaler.UnmarshalJSON(val); err != nil {
err = wrapSkipFunc(err, "unmarshal method")
// TODO: Avoid wrapping semantic, syntactic, or I/O errors.
return &SemanticError{action: "unmarshal", JSONKind: val.Kind(), GoType: t, Err: err}
}
return nil
}
case textUnmarshalerType:
fncs.nonDefault = true
fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
xd := export.Decoder(dec)
var flags jsonwire.ValueFlags
val, err := xd.ReadValue(&flags)
if err != nil {
return err // must be a syntactic or I/O error
}
if val.Kind() != '"' {
err = errors.New("JSON value must be string type")
return &SemanticError{action: "unmarshal", JSONKind: val.Kind(), GoType: t, Err: err}
}
s := jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
unmarshaler := va.Addr().Interface().(encoding.TextUnmarshaler)
if err := unmarshaler.UnmarshalText(s); err != nil {
err = wrapSkipFunc(err, "unmarshal method")
// TODO: Avoid wrapping semantic, syntactic, or I/O errors.
return &SemanticError{action: "unmarshal", JSONKind: val.Kind(), GoType: t, Err: err}
}
return nil
}
}
return fncs
}
// implementsWhich is like t.Implements(ifaceType) for a list of interfaces,
// but checks whether either t or reflect.PointerTo(t) implements the interface.
func implementsWhich(t reflect.Type, ifaceTypes ...reflect.Type) (which reflect.Type) {
for _, ifaceType := range ifaceTypes {
if t.Implements(ifaceType) || reflect.PointerTo(t).Implements(ifaceType) {
return ifaceType
}
}
return nil
}