// Copyright 2024 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 (
	
	
	
	

	
	
	jsonv2 
)

// Inject functionality into v2 to properly handle v1 types.
func init() {
	internal.TransformMarshalError = transformMarshalError
	internal.TransformUnmarshalError = transformUnmarshalError
	internal.NewMarshalerError = func( any,  error,  string) error {
		return &MarshalerError{reflect.TypeOf(), , }
	}

	internal.NewRawNumber = func() any { return new(Number) }
	internal.RawNumberOf = func( []byte) any { return Number() }
}

func transformMarshalError( any,  error) error {
	// Historically, errors returned from Marshal methods were wrapped
	// in a [MarshalerError]. This is directly performed by the v2 package
	// via the injected [internal.NewMarshalerError] constructor
	// while operating under [ReportErrorsWithLegacySemantics].
	// Note that errors from a Marshal method were always wrapped,
	// even if wrapped for multiple layers.
	if ,  := .(*jsonv2.SemanticError);  != nil {
		if .Err == nil {
			// Historically, this was only reported for unserializable types
			// like complex numbers, channels, functions, and unsafe.Pointers.
			return &UnsupportedTypeError{Type: .GoType}
		} else {
			// Historically, this was only reported for NaN or ±Inf values
			// and cycles detected in the value.
			// The Val used to be populated with the reflect.Value,
			// but this is no longer supported.
			 := .Err.Error()
			if .Err == internal.ErrCycle && .GoType != nil {
				 += " via " + .GoType.String()
			}
			 = strings.TrimPrefix(, "unsupported value: ")
			return &UnsupportedValueError{Str: }
		}
	} else if  {
		return (*UnsupportedValueError)(nil)
	}
	if ,  := .(*MarshalerError);  != nil {
		.Err = transformSyntacticError(.Err)
		return 
	}
	return transformSyntacticError()
}

func transformUnmarshalError( any,  error) error {
	// Historically, errors from Unmarshal methods were never wrapped and
	// returned verbatim while operating under [ReportErrorsWithLegacySemantics].
	if ,  := .(*jsonv2.SemanticError);  != nil {
		if .Err == internal.ErrNonNilReference {
			return &InvalidUnmarshalError{.GoType}
		}
		if .Err == jsonv2.ErrUnknownName {
			return fmt.Errorf("json: unknown field %q", .JSONPointer.LastToken())
		}

		// Historically, UnmarshalTypeError has always been inconsistent
		// about how it reported position information.
		//
		// The Struct field now points to the root type,
		// rather than some intermediate struct in the path.
		// This better matches the original intent of the field based
		// on how the Error message was formatted.
		//
		// For a representation closer to the historical representation,
		// we switch the '/'-delimited representation of a JSON pointer
		// to use a '.'-delimited representation. This may be ambiguous,
		// but the prior representation was always ambiguous as well.
		// Users that care about precise positions should use v2 errors
		// by disabling [ReportErrorsWithLegacySemantics].
		//
		// The introduction of a Err field is new to the v1-to-v2 migration
		// and allows us to preserve stronger error information
		// that may be surfaced by the v2 package.
		//
		// See https://go.dev/issue/43126
		var  string
		switch .JSONKind {
		case 'n', '"', '0':
			 = .JSONKind.String()
		case 'f', 't':
			 = "bool"
		case '[', ']':
			 = "array"
		case '{', '}':
			 = "object"
		}
		if len(.JSONValue) > 0 {
			 := .Err == strconv.ErrRange || .Err == strconv.ErrSyntax
			 := func( reflect.Type) bool {
				if  == nil {
					return false
				}
				switch .Kind() {
				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
					reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
					reflect.Float32, reflect.Float64:
					return true
				}
				return false
			}
			if  && (.GoType) {
				 = "number"
				if .JSONKind == '"' {
					.JSONValue, _ = jsontext.AppendUnquote(nil, .JSONValue)
				}
				.Err = nil
			}
			 += " " + string(.JSONValue)
		}
		var  string
		if  := reflect.TypeOf();  != nil && .JSONPointer != "" {
			if .Kind() == reflect.Pointer {
				 = .Elem()
			}
			 = .Name()
		}
		 := string(.JSONPointer)
		 = strings.TrimPrefix(, "/")
		 = strings.ReplaceAll(, "/", ".")
		return &UnmarshalTypeError{
			Value:  ,
			Type:   .GoType,
			Offset: .ByteOffset,
			Struct: ,
			Field:  ,
			Err:    transformSyntacticError(.Err),
		}
	} else if  {
		return (*UnmarshalTypeError)(nil)
	}
	return transformSyntacticError()
}