// 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.

//go:build goexperiment.jsonv2

package json

import (
	
	
	
	

	
	
	
	
	
)

var errNonStringValue = errors.New("JSON value must be string type")

// Interfaces for custom serialization.
var (
	jsonMarshalerType       = reflect.TypeFor[Marshaler]()
	jsonMarshalerToType     = reflect.TypeFor[MarshalerTo]()
	jsonUnmarshalerType     = reflect.TypeFor[Unmarshaler]()
	jsonUnmarshalerFromType = reflect.TypeFor[UnmarshalerFrom]()
	textAppenderType        = reflect.TypeFor[encoding.TextAppender]()
	textMarshalerType       = reflect.TypeFor[encoding.TextMarshaler]()
	textUnmarshalerType     = reflect.TypeFor[encoding.TextUnmarshaler]()

	allMarshalerTypes   = []reflect.Type{jsonMarshalerToType, jsonMarshalerType, textAppenderType, textMarshalerType}
	allUnmarshalerTypes = []reflect.Type{jsonUnmarshalerFromType, jsonUnmarshalerType, textUnmarshalerType}
	allMethodTypes      = append(allMarshalerTypes, allUnmarshalerTypes...)
)

// Marshaler is implemented by types that can marshal themselves.
// It is recommended that types implement [MarshalerTo] unless the implementation
// is trying to avoid directly depending on the "jsontext" package.
//
// Implementations should return a buffer that is safe
// for the caller to retain and potentially mutate.
//
// Implementations must not return [errors.ErrUnsupported].
//
// If the returned error is a [SemanticError], then unpopulated fields
// of the error may be populated by [json] with additional context.
// Errors of other types are wrapped within a [SemanticError].
//
// Implementations should assume [Deterministic] is true and return
// deterministic output.
type Marshaler interface {
	MarshalJSON() ([]byte, error)
}

// MarshalerTo is implemented by types that can marshal themselves.
// It is recommended that types implement MarshalerTo instead of [Marshaler]
// since it is both more performant and more flexible.
// If a type implements both Marshaler and MarshalerTo,
// then MarshalerTo 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.
// Alternatively, it may return [errors.ErrUnsupported] without mutating
// the Encoder. The "json" package calling the method will
// use the next available JSON representation for the receiver type,
// as described in [Marshal].
// Implementations must not retain the pointer to [jsontext.Encoder].
//
// If the returned error is a [SemanticError], then unpopulated fields
// of the error may be populated by [json] with additional context.
// Errors of other types are wrapped within a [SemanticError],
// except for IO errors.
//
// The MarshalJSONTo method should not be called directly as it may
// return sentinel errors that need special handling.
// Users should instead call [MarshalEncode], which handles such cases.
//
// Implementations should inspect the marshal options from
// [jsontext.Encoder.Options] and adjust behavior to respect the options as
// necessary.
//
// The following options may be relevant to MarshalerTo implementations:
//
// - [Deterministic]: if the implementation may produce non-deterministic output
// - [StringifyNumbers]: if the type is represented as a JSON number
//
// Several options, such as [FormatNilSliceAsNull], apply only to native Go
// types. Thus, these options are typically not directly relevant to
// MarshalerTo implementations. However, types representing a composite type
// should marshal contained types using [MarshalEncode] to ensure these options
// apply to the contained types. Similarly, [WithMarshalers] may influence
// marshaling of any contained type within a composite type.
//
// All other options are automatically handled outside of the MarshalerTo
// implementation, and thus are not relevant to implementations.
type MarshalerTo interface {
	MarshalJSONTo(*jsontext.Encoder) error
}

// Unmarshaler is implemented by types that can unmarshal themselves.
// It is recommended that types implement [UnmarshalerFrom] unless the implementation
// is trying to avoid a direct 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.
// It is recommended that UnmarshalJSON implement merge semantics
// when unmarshaling into a pre-populated value, as described in [Unmarshal].
//
// Implementations must not retain or mutate the input []byte.
//
// Implementations must not return [errors.ErrUnsupported].
//
// If the returned error is a [SemanticError], then unpopulated fields
// of the error may be populated by [json] with additional context.
// Errors of other types are wrapped within a [SemanticError].
type Unmarshaler interface {
	UnmarshalJSON([]byte) error
}

// UnmarshalerFrom is implemented by types that can unmarshal themselves.
// It is recommended that types implement UnmarshalerFrom instead of [Unmarshaler]
// since this is both more performant and more flexible.
// If a type implements both Unmarshaler and UnmarshalerFrom,
// then UnmarshalerFrom 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 UnmarshalJSONFrom implement merge semantics when
// unmarshaling into a pre-populated value, as described in [Unmarshal].
// Alternatively, it may return [errors.ErrUnsupported] without mutating
// the Decoder. The "json" package calling the method will
// use the next available JSON representation for the receiver type.
// Implementations must not retain the pointer to [jsontext.Decoder].
//
// If the returned error is a [SemanticError], then unpopulated fields
// of the error may be populated by [json] with additional context.
// Errors of other types are wrapped within a [SemanticError],
// except for [jsontext.SyntacticError]s and IO errors.
//
// The UnmarshalJSONFrom method should not be called directly as it may
// return sentinel errors that need special handling.
// Users should instead call [UnmarshalDecode], which handles such cases.
//
// Implementations should inspect the unmarshal options from
// [jsontext.Decoder.Options] and adjust behavior to respect the options as
// necessary.
//
// The following options may be relevant to UnmarshalerFrom implementations:
//
// - [StringifyNumbers]: if the type is represented as a JSON number
//
// Several options, such as [FormatNilSliceAsNull], apply only to native Go
// types. Thus, these options are typically not directly relevant to
// UnmarshalerFrom implementations. However, types representing a composite
// type should unmarshal contained types using [UnmarshalDecode] to ensure
// these options apply to the contained types. Similarly, [WithUnmarshalers]
// may influence unmarshaling of any contained type within a composite type.
//
// All other options are automatically handled outside of the UnmarshalerFrom
// implementation, and thus are not relevant to implementations.
type UnmarshalerFrom interface {
	UnmarshalJSONFrom(*jsontext.Decoder) error
}

func ( *arshaler,  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 .Kind() == reflect.Pointer || .Kind() == reflect.Interface {
		return 
	}

	if ,  := implements(, textMarshalerType);  {
		.nonDefault = true
		 := .marshal
		.marshal = func( *jsontext.Encoder,  addressableValue,  *jsonopts.Struct) error {
			if .Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
				(( && .forcedAddr) ||
					(export.Encoder().Tokens.Last.NeedObjectName()) && .Kind() == reflect.String) {
				// Do not call MarshalText on unaddressable values and map keys of string kind.
				return (, , )
			}
			,  := reflect.TypeAssert[encoding.TextMarshaler](.Addr())
			if  := export.Encoder().AppendRaw('"', false, func( []byte) ([]byte, error) {
				,  := .MarshalText()
				return append(, ...), 
			});  != nil {
				 = wrapErrUnsupported(, "MarshalText method")
				if .Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return internal.NewMarshalerError(.Addr().Interface(), , "MarshalText") // unlike unmarshal, always wrapped
				}
				if !isSemanticError() && !export.IsIOError() {
					 = newMarshalErrorBefore(, , )
				}
				return 
			}
			return nil
		}
	}

	if ,  := implements(, textAppenderType);  {
		.nonDefault = true
		 := .marshal
		.marshal = func( *jsontext.Encoder,  addressableValue,  *jsonopts.Struct) ( error) {
			if .Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
				(( && .forcedAddr) ||
					(export.Encoder().Tokens.Last.NeedObjectName()) && .Kind() == reflect.String) {
				// Do not call AppendText on unaddressable values and map keys of string kind.
				return (, , )
			}
			,  := reflect.TypeAssert[encoding.TextAppender](.Addr())
			if  := export.Encoder().AppendRaw('"', false, .AppendText);  != nil {
				 = wrapErrUnsupported(, "AppendText method")
				if .Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return internal.NewMarshalerError(.Addr().Interface(), , "AppendText") // unlike unmarshal, always wrapped
				}
				if !isSemanticError() && !export.IsIOError() {
					 = newMarshalErrorBefore(, , )
				}
				return 
			}
			return nil
		}
	}

	if ,  := implements(, jsonMarshalerType);  {
		.nonDefault = true
		 := .marshal
		.marshal = func( *jsontext.Encoder,  addressableValue,  *jsonopts.Struct) error {
			if .Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
				(( && .forcedAddr) || export.Encoder().Tokens.Last.NeedObjectName()) {
				// Do not call MarshalJSON on unaddressable values and map keys.
				return (, , )
			}
			,  := reflect.TypeAssert[Marshaler](.Addr())
			,  := .MarshalJSON()
			if  != nil {
				 = wrapErrUnsupported(, "MarshalJSON method")
				if .Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return internal.NewMarshalerError(.Addr().Interface(), , "MarshalJSON") // unlike unmarshal, always wrapped
				}
				 = newMarshalErrorBefore(, , )
				return collapseSemanticErrors()
			}
			if  := .WriteValue();  != nil {
				if .Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return internal.NewMarshalerError(.Addr().Interface(), , "MarshalJSON") // unlike unmarshal, always wrapped
				}
				if isSyntacticError() {
					 = newMarshalErrorBefore(, , )
				}
				return 
			}
			return nil
		}
	}

	if ,  := implements(, jsonMarshalerToType);  {
		.nonDefault = true
		 := .marshal
		.marshal = func( *jsontext.Encoder,  addressableValue,  *jsonopts.Struct) error {
			if .Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
				(( && .forcedAddr) || export.Encoder().Tokens.Last.NeedObjectName()) {
				// Do not call MarshalJSONTo on unaddressable values and map keys.
				return (, , )
			}
			 := export.Encoder()
			,  := .Tokens.DepthLength()
			.Flags.Set(jsonflags.WithinArshalCall | 1)
			,  := reflect.TypeAssert[MarshalerTo](.Addr())
			 := .MarshalJSONTo()
			.Flags.Set(jsonflags.WithinArshalCall | 0)
			,  := .Tokens.DepthLength()
			if ( !=  || +1 != ) &&  == nil {
				 = errNonSingularValue
			}
			if  != nil {
				if errors.Is(, errors.ErrUnsupported) {
					if  ==  &&  ==  {
						return (, , )
					}
					 = errUnsupportedMutation
				}
				if .Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return internal.NewMarshalerError(.Addr().Interface(), , "MarshalJSONTo") // unlike unmarshal, always wrapped
				}
				if !export.IsIOError() {
					 = newSemanticErrorWithPosition(, , , , )
				}
				return 
			}
			return nil
		}
	}

	if ,  := implements(, textUnmarshalerType);  {
		.nonDefault = true
		.unmarshal = func( *jsontext.Decoder,  addressableValue,  *jsonopts.Struct) error {
			 := export.Decoder()
			var  jsonwire.ValueFlags
			,  := .ReadValue(&)
			if  != nil {
				return  // must be a syntactic or I/O error
			}
			if .Kind() == 'n' {
				if !.Flags.Get(jsonflags.MergeWithLegacySemantics) {
					.SetZero()
				}
				return nil
			}
			if .Kind() != '"' {
				return newUnmarshalErrorAfter(, , errNonStringValue)
			}
			 := jsonwire.UnquoteMayCopy(, .IsVerbatim())
			,  := reflect.TypeAssert[encoding.TextUnmarshaler](.Addr())
			if  := .UnmarshalText();  != nil {
				 = wrapErrUnsupported(, "UnmarshalText method")
				if .Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return  // unlike marshal, never wrapped
				}
				if !isSemanticError() && !isSyntacticError() && !export.IsIOError() {
					 = newUnmarshalErrorAfter(, , )
				}
				return 
			}
			return nil
		}
	}

	if ,  := implements(, jsonUnmarshalerType);  {
		.nonDefault = true
		 := .unmarshal
		.unmarshal = func( *jsontext.Decoder,  addressableValue,  *jsonopts.Struct) error {
			if .Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
				export.Decoder().Tokens.Last.NeedObjectName() {
				// Do not call UnmarshalJSON on map keys.
				return (, , )
			}
			,  := .ReadValue()
			if  != nil {
				return  // must be a syntactic or I/O error
			}
			,  := reflect.TypeAssert[Unmarshaler](.Addr())
			if  := .UnmarshalJSON();  != nil {
				 = wrapErrUnsupported(, "UnmarshalJSON method")
				if .Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					return  // unlike marshal, never wrapped
				}
				 = newUnmarshalErrorAfter(, , )
				return collapseSemanticErrors()
			}
			return nil
		}
	}

	if ,  := implements(, jsonUnmarshalerFromType);  {
		.nonDefault = true
		 := .unmarshal
		.unmarshal = func( *jsontext.Decoder,  addressableValue,  *jsonopts.Struct) error {
			if .Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
				export.Decoder().Tokens.Last.NeedObjectName() {
				// Do not call UnmarshalJSONFrom on map keys.
				return (, , )
			}
			 := export.Decoder()
			,  := .Tokens.DepthLength()
			if  == 1 && .AtEOF() {
				return io.EOF // check EOF early to avoid fn reporting an EOF
			}
			.Flags.Set(jsonflags.WithinArshalCall | 1)
			,  := reflect.TypeAssert[UnmarshalerFrom](.Addr())
			 := .UnmarshalJSONFrom()
			.Flags.Set(jsonflags.WithinArshalCall | 0)
			,  := .Tokens.DepthLength()
			if ( !=  || +1 != ) &&  == nil {
				 = errNonSingularValue
			}
			if  != nil {
				if errors.Is(, errors.ErrUnsupported) {
					if  ==  &&  ==  {
						return (, , )
					}
					 = errUnsupportedMutation
				}
				if .Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
					if  := .SkipUntil(, +1);  != nil {
						return 
					}
					return  // unlike marshal, never wrapped
				}
				if !isSyntacticError() && !export.IsIOError() {
					 = newSemanticErrorWithPosition(, , , , )
				}
				return 
			}
			return nil
		}
	}

	return 
}

// implementsAny is like t.Implements(ifaceType) for a list of interfaces,
// but checks whether either t or reflect.PointerTo(t) implements the interface.
func ( reflect.Type,  ...reflect.Type) bool {
	for ,  := range  {
		if ,  := implements(, );  {
			return true
		}
	}
	return false
}

// implements is like t.Implements(ifaceType) but checks whether
// either t or reflect.PointerTo(t) implements the interface.
// It also reports whether the value needs to be addressed
// in order to satisfy the interface.
func (,  reflect.Type) (,  bool) {
	switch {
	case .Implements():
		return false, true
	case reflect.PointerTo().Implements():
		return true, true
	default:
		return false, false
	}
}