// Copyright 2022 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 protoreflect

import (
	
	
	
	

	
)

// Equal reports whether v1 and v2 are recursively equal.
//
//   - Values of different types are always unequal.
//
//   - Bytes values are equal if they contain identical bytes.
//     Empty bytes (regardless of nil-ness) are considered equal.
//
//   - Floating point values are equal if they contain the same value.
//     Unlike the == operator, a NaN is equal to another NaN.
//
//   - Enums are equal if they contain the same number.
//     Since [Value] does not contain an enum descriptor,
//     enum values do not consider the type of the enum.
//
//   - Other scalar values are equal if they contain the same value.
//
//   - [Message] values are equal if they belong to the same message descriptor,
//     have the same set of populated known and extension field values,
//     and the same set of unknown fields values.
//
//   - [List] values are equal if they are the same length and
//     each corresponding element is equal.
//
//   - [Map] values are equal if they have the same set of keys and
//     the corresponding value for each key is equal.
func ( Value) ( Value) bool {
	return equalValue(, )
}

func (,  Value) bool {
	 := .typ == .typ
	switch .typ {
	case nilType:
		return 
	case boolType:
		return  && .Bool() == .Bool()
	case int32Type, int64Type:
		return  && .Int() == .Int()
	case uint32Type, uint64Type:
		return  && .Uint() == .Uint()
	case float32Type, float64Type:
		return  && equalFloat(.Float(), .Float())
	case stringType:
		return  && .String() == .String()
	case bytesType:
		return  && bytes.Equal(.Bytes(), .Bytes())
	case enumType:
		return  && .Enum() == .Enum()
	default:
		switch x := .Interface().(type) {
		case Message:
			,  := .Interface().(Message)
			return  && equalMessage(, )
		case List:
			,  := .Interface().(List)
			return  && equalList(, )
		case Map:
			,  := .Interface().(Map)
			return  && equalMap(, )
		default:
			panic(fmt.Sprintf("unknown type: %T", ))
		}
	}
}

// equalFloat compares two floats, where NaNs are treated as equal.
func (,  float64) bool {
	if math.IsNaN() || math.IsNaN() {
		return math.IsNaN() && math.IsNaN()
	}
	return  == 
}

// equalMessage compares two messages.
func (,  Message) bool {
	if .Descriptor() != .Descriptor() {
		return false
	}

	 := 0
	 := true
	.Range(func( FieldDescriptor,  Value) bool {
		++
		 := .Get()
		 = .Has() && equalValue(, )
		return 
	})
	if ! {
		return false
	}
	 := 0
	.Range(func( FieldDescriptor,  Value) bool {
		++
		return true
	})
	if  !=  {
		return false
	}

	return equalUnknown(.GetUnknown(), .GetUnknown())
}

// equalList compares two lists.
func (,  List) bool {
	if .Len() != .Len() {
		return false
	}
	for  := .Len() - 1;  >= 0; -- {
		if !equalValue(.Get(), .Get()) {
			return false
		}
	}
	return true
}

// equalMap compares two maps.
func (,  Map) bool {
	if .Len() != .Len() {
		return false
	}
	 := true
	.Range(func( MapKey,  Value) bool {
		 := .Get()
		 = .Has() && equalValue(, )
		return 
	})
	return 
}

// equalUnknown compares unknown fields by direct comparison on the raw bytes
// of each individual field number.
func (,  RawFields) bool {
	if len() != len() {
		return false
	}
	if bytes.Equal([]byte(), []byte()) {
		return true
	}

	 := make(map[FieldNumber]RawFields)
	 := make(map[FieldNumber]RawFields)
	for len() > 0 {
		, ,  := protowire.ConsumeField()
		[] = append([], [:]...)
		 = [:]
	}
	for len() > 0 {
		, ,  := protowire.ConsumeField()
		[] = append([], [:]...)
		 = [:]
	}
	return reflect.DeepEqual(, )
}