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

package impl

import (
	

	
	
	
)

func ( protoiface.EqualInput) protoiface.EqualOutput {
	return protoiface.EqualOutput{Equal: equalMessage(.MessageA, .MessageB)}
}

// equalMessage is a fast-path variant of protoreflect.equalMessage.
// It takes advantage of the internal messageState type to avoid
// unnecessary allocations, type assertions.
func (,  protoreflect.Message) bool {
	if  == nil ||  == nil {
		return  == 
	}
	if .Descriptor() != .Descriptor() {
		return false
	}

	,  := .(*messageState)
	if ! {
		return protoreflect.ValueOfMessage().Equal(protoreflect.ValueOfMessage())
	}
	,  := .(*messageState)
	if ! {
		return protoreflect.ValueOfMessage().Equal(protoreflect.ValueOfMessage())
	}

	 := .messageInfo()
	 := .messageInfo()
	if  !=  {
		return protoreflect.ValueOfMessage().Equal(protoreflect.ValueOfMessage())
	}
	.init()
	// Compares regular fields
	// Modified Message.Range code that compares two messages of the same type
	// while going over the fields.
	for ,  := range .rangeInfos {
		var  protoreflect.FieldDescriptor
		var ,  protoreflect.Value

		switch ri := .(type) {
		case *fieldInfo:
			 := .has(.pointer())
			 := .has(.pointer())
			if  !=  {
				return false
			}
			if ! {
				continue
			}
			 = .fieldDesc
			 = .get(.pointer())
			 = .get(.pointer())
		case *oneofInfo:
			 := .which(.pointer())
			 := .which(.pointer())
			if  !=  {
				return false
			}
			if  <= 0 {
				continue
			}
			 := .fields[]
			 = .fieldDesc
			 = .get(.pointer())
			 = .get(.pointer())
		}

		if !equalValue(, , ) {
			return false
		}
	}

	// Compare extensions.
	// This is more complicated because mx or my could have empty/nil extension maps,
	// however some populated extension map values are equal to nil extension maps.
	 := .extensionMap(.pointer())
	 := .extensionMap(.pointer())
	if  != nil {
		for ,  := range * {
			 := .Type().TypeDescriptor()
			 := .Value()
			var  ExtensionField
			 := false
			if  != nil {
				,  = (*)[]
			}
			// We need to treat empty lists as equal to nil values
			if  == nil || ! {
				if .IsList() && .List().Len() == 0 {
					continue
				}
				return false
			}

			if !equalValue(, , .Value()) {
				return false
			}
		}
	}
	if  != nil {
		// emy may have extensions emx does not have, need to check them as well
		for ,  := range * {
			if  != nil {
				// emx has the field, so we already checked it
				if ,  := (*)[];  {
					continue
				}
			}
			// Empty lists are equal to nil
			if .Type().TypeDescriptor().IsList() && .Value().List().Len() == 0 {
				continue
			}

			// Cant be equal if the extension is populated
			return false
		}
	}

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

func ( protoreflect.FieldDescriptor, ,  protoreflect.Value) bool {
	// slow path
	if .Kind() != protoreflect.MessageKind {
		return .Equal()
	}

	// fast path special cases
	if .IsMap() {
		if .MapValue().Kind() == protoreflect.MessageKind {
			return equalMessageMap(.Map(), .Map())
		}
		return .Equal()
	}

	if .IsList() {
		return equalMessageList(.List(), .List())
	}

	return equalMessage(.Message(), .Message())
}

// Mostly copied from protoreflect.equalMap.
// This variant only works for messages as map types.
// All other map types should be handled via Value.Equal.
func (,  protoreflect.Map) bool {
	if .Len() != .Len() {
		return false
	}
	 := true
	.Range(func( protoreflect.MapKey,  protoreflect.Value) bool {
		if !.Has() {
			 = false
			return false
		}
		 := .Get()
		 = equalMessage(.Message(), .Message())
		return 
	})
	return 
}

// Mostly copied from protoreflect.equalList.
// The only change is the usage of equalImpl instead of protoreflect.equalValue.
func (,  protoreflect.List) bool {
	if .Len() != .Len() {
		return false
	}
	for  := 0;  < .Len(); ++ {
		// We only operate on messages here since equalImpl will not call us in any other case.
		if !equalMessage(.Get().Message(), .Get().Message()) {
			return false
		}
	}
	return true
}

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

	 := make(map[protoreflect.FieldNumber]protoreflect.RawFields)
	 := make(map[protoreflect.FieldNumber]protoreflect.RawFields)
	for len() > 0 {
		, ,  := protowire.ConsumeField()
		[] = append([], [:]...)
		 = [:]
	}
	for len() > 0 {
		, ,  := protowire.ConsumeField()
		[] = append([], [:]...)
		 = [:]
	}
	if len() != len() {
		return false
	}

	for ,  := range  {
		if ,  := []; ! || !bytes.Equal([]byte(), []byte()) {
			return false
		}
	}

	return true
}