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

	
	ptag 
	
	
	
	
	
)

// legacyWrapMessage wraps v as a protoreflect.Message,
// where v must be a *struct kind and not implement the v2 API already.
func ( reflect.Value) protoreflect.Message {
	 := .Type()
	if .Kind() != reflect.Ptr || .Elem().Kind() != reflect.Struct {
		return aberrantMessage{v: }
	}
	 := legacyLoadMessageInfo(, "")
	return .MessageOf(.Interface())
}

// legacyLoadMessageType dynamically loads a protoreflect.Type for t,
// where t must be not implement the v2 API already.
// The provided name is used if it cannot be determined from the message.
func ( reflect.Type,  protoreflect.FullName) protoreflect.MessageType {
	if .Kind() != reflect.Ptr || .Elem().Kind() != reflect.Struct {
		return aberrantMessageType{}
	}
	return legacyLoadMessageInfo(, )
}

var legacyMessageTypeCache sync.Map // map[reflect.Type]*MessageInfo

// legacyLoadMessageInfo dynamically loads a *MessageInfo for t,
// where t must be a *struct kind and not implement the v2 API already.
// The provided name is used if it cannot be determined from the message.
func ( reflect.Type,  protoreflect.FullName) *MessageInfo {
	// Fast-path: check if a MessageInfo is cached for this concrete type.
	if ,  := legacyMessageTypeCache.Load();  {
		return .(*MessageInfo)
	}

	// Slow-path: derive message descriptor and initialize MessageInfo.
	 := &MessageInfo{
		Desc:          legacyLoadMessageDesc(, ),
		GoReflectType: ,
	}

	var ,  bool
	 := reflect.Zero().Interface()
	if _,  = .(legacyMarshaler);  {
		.methods.Marshal = legacyMarshal

		// We have no way to tell whether the type's Marshal method
		// supports deterministic serialization or not, but this
		// preserves the v1 implementation's behavior of always
		// calling Marshal methods when present.
		.methods.Flags |= protoiface.SupportMarshalDeterministic
	}
	if _,  = .(legacyUnmarshaler);  {
		.methods.Unmarshal = legacyUnmarshal
	}
	if ,  := .(legacyMerger);  || ( && ) {
		.methods.Merge = legacyMerge
	}

	if ,  := legacyMessageTypeCache.LoadOrStore(, );  {
		return .(*MessageInfo)
	}
	return 
}

var legacyMessageDescCache sync.Map // map[reflect.Type]protoreflect.MessageDescriptor

// LegacyLoadMessageDesc returns an MessageDescriptor derived from the Go type,
// which should be a *struct kind and must not implement the v2 API already.
//
// This is exported for testing purposes.
func ( reflect.Type) protoreflect.MessageDescriptor {
	return legacyLoadMessageDesc(, "")
}
func ( reflect.Type,  protoreflect.FullName) protoreflect.MessageDescriptor {
	// Fast-path: check if a MessageDescriptor is cached for this concrete type.
	if ,  := legacyMessageDescCache.Load();  {
		return .(protoreflect.MessageDescriptor)
	}

	// Slow-path: initialize MessageDescriptor from the raw descriptor.
	 := reflect.Zero().Interface()
	if ,  := .(protoreflect.ProtoMessage);  {
		panic(fmt.Sprintf("%v already implements proto.Message", ))
	}
	,  := .(messageV1)
	if ! {
		return aberrantLoadMessageDesc(, )
	}

	// If this is a dynamic message type where there isn't a 1-1 mapping between
	// Go and protobuf types, calling the Descriptor method on the zero value of
	// the message type isn't likely to work. If it panics, swallow the panic and
	// continue as if the Descriptor method wasn't present.
	,  := func() ([]byte, []int) {
		defer func() {
			recover()
		}()
		return .Descriptor()
	}()
	if  == nil {
		return aberrantLoadMessageDesc(, )
	}

	// If the Go type has no fields, then this might be a proto3 empty message
	// from before the size cache was added. If there are any fields, check to
	// see that at least one of them looks like something we generated.
	if .Elem().Kind() == reflect.Struct {
		if  := .Elem().NumField();  > 0 {
			 := false
			for  := 0;  < ; ++ {
				 := .Elem().Field()
				if .Tag.Get("protobuf") != "" || .Tag.Get("protobuf_oneof") != "" || strings.HasPrefix(.Name, "XXX_") {
					 = true
					break
				}
			}
			if ! {
				return aberrantLoadMessageDesc(, )
			}
		}
	}

	 := legacyLoadFileDesc().Messages().Get([0])
	for ,  := range [1:] {
		 = .Messages().Get()
	}
	if  != "" && .FullName() !=  {
		panic(fmt.Sprintf("mismatching message name: got %v, want %v", .FullName(), ))
	}
	if ,  := legacyMessageDescCache.LoadOrStore(, );  {
		return .(protoreflect.MessageDescriptor)
	}
	return 
}

var (
	aberrantMessageDescLock  sync.Mutex
	aberrantMessageDescCache map[reflect.Type]protoreflect.MessageDescriptor
)

// aberrantLoadMessageDesc returns an MessageDescriptor derived from the Go type,
// which must not implement protoreflect.ProtoMessage or messageV1.
//
// This is a best-effort derivation of the message descriptor using the protobuf
// tags on the struct fields.
func ( reflect.Type,  protoreflect.FullName) protoreflect.MessageDescriptor {
	aberrantMessageDescLock.Lock()
	defer aberrantMessageDescLock.Unlock()
	if aberrantMessageDescCache == nil {
		aberrantMessageDescCache = make(map[reflect.Type]protoreflect.MessageDescriptor)
	}
	return aberrantLoadMessageDescReentrant(, )
}
func ( reflect.Type,  protoreflect.FullName) protoreflect.MessageDescriptor {
	// Fast-path: check if an MessageDescriptor is cached for this concrete type.
	if ,  := aberrantMessageDescCache[];  {
		return 
	}

	// Slow-path: construct a descriptor from the Go struct type (best-effort).
	// Cache the MessageDescriptor early on so that we can resolve internal
	// cyclic references.
	 := &filedesc.Message{L2: new(filedesc.MessageL2)}
	.L0.FullName = aberrantDeriveMessageName(, )
	.L0.ParentFile = filedesc.SurrogateProto2
	aberrantMessageDescCache[] = 

	if .Kind() != reflect.Ptr || .Elem().Kind() != reflect.Struct {
		return 
	}

	// Try to determine if the message is using proto3 by checking scalars.
	for  := 0;  < .Elem().NumField(); ++ {
		 := .Elem().Field()
		if  := .Tag.Get("protobuf");  != "" {
			switch .Type.Kind() {
			case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
				.L0.ParentFile = filedesc.SurrogateProto3
			}
			for ,  := range strings.Split(, ",") {
				if  == "proto3" {
					.L0.ParentFile = filedesc.SurrogateProto3
				}
			}
		}
	}

	// Obtain a list of oneof wrapper types.
	var  []reflect.Type
	for ,  := range []string{"XXX_OneofFuncs", "XXX_OneofWrappers"} {
		if ,  := .MethodByName();  {
			for ,  := range .Func.Call([]reflect.Value{reflect.Zero(.Type.In(0))}) {
				if ,  := .Interface().([]interface{});  {
					for ,  := range  {
						 = append(, reflect.TypeOf())
					}
				}
			}
		}
	}

	// Obtain a list of the extension ranges.
	if ,  := .MethodByName("ExtensionRangeArray");  {
		 := .Func.Call([]reflect.Value{reflect.Zero(.Type.In(0))})[0]
		for  := 0;  < .Len(); ++ {
			 := .Index()
			.L2.ExtensionRanges.List = append(.L2.ExtensionRanges.List, [2]protoreflect.FieldNumber{
				protoreflect.FieldNumber(.FieldByName("Start").Int()),
				protoreflect.FieldNumber(.FieldByName("End").Int() + 1),
			})
			.L2.ExtensionRangeOptions = append(.L2.ExtensionRangeOptions, nil)
		}
	}

	// Derive the message fields by inspecting the struct fields.
	for  := 0;  < .Elem().NumField(); ++ {
		 := .Elem().Field()
		if  := .Tag.Get("protobuf");  != "" {
			 := .Tag.Get("protobuf_key")
			 := .Tag.Get("protobuf_val")
			aberrantAppendField(, .Type, , , )
		}
		if  := .Tag.Get("protobuf_oneof");  != "" {
			 := len(.L2.Oneofs.List)
			.L2.Oneofs.List = append(.L2.Oneofs.List, filedesc.Oneof{})
			 := &.L2.Oneofs.List[]
			.L0.FullName = .FullName().Append(protoreflect.Name())
			.L0.ParentFile = .L0.ParentFile
			.L0.Parent = 
			.L0.Index = 

			for ,  := range  {
				if .Implements(.Type) {
					 := .Elem().Field(0)
					if  := .Tag.Get("protobuf");  != "" {
						aberrantAppendField(, .Type, , "", "")
						 := &.L2.Fields.List[len(.L2.Fields.List)-1]
						.L1.ContainingOneof = 
						.L1.Fields.List = append(.L1.Fields.List, )
					}
				}
			}
		}
	}

	return 
}

func ( reflect.Type,  protoreflect.FullName) protoreflect.FullName {
	if .IsValid() {
		return 
	}
	func() {
		defer func() { recover() }() // swallow possible nil panics
		if ,  := reflect.Zero().Interface().(interface{ () string });  {
			 = protoreflect.FullName(.())
		}
	}()
	if .IsValid() {
		return 
	}
	if .Kind() == reflect.Ptr {
		 = .Elem()
	}
	return AberrantDeriveFullName()
}

func ( *filedesc.Message,  reflect.Type, , ,  string) {
	 := 
	 := .Kind() == reflect.Ptr && .Elem().Kind() != reflect.Struct
	 := .Kind() == reflect.Slice && .Elem().Kind() != reflect.Uint8
	if  ||  {
		 = .Elem()
	}
	 := ptag.Unmarshal(, , placeholderEnumValues{}).(*filedesc.Field)

	// Append field descriptor to the message.
	 := len(.L2.Fields.List)
	.L2.Fields.List = append(.L2.Fields.List, *)
	 = &.L2.Fields.List[]
	.L0.FullName = .FullName().Append(.Name())
	.L0.ParentFile = .L0.ParentFile
	.L0.Parent = 
	.L0.Index = 

	if .L1.IsWeak || .L1.HasPacked {
		.L1.Options = func() protoreflect.ProtoMessage {
			 := descopts.Field.ProtoReflect().New()
			if .L1.IsWeak {
				.Set(.Descriptor().Fields().ByName("weak"), protoreflect.ValueOfBool(true))
			}
			if .L1.HasPacked {
				.Set(.Descriptor().Fields().ByName("packed"), protoreflect.ValueOfBool(.L1.IsPacked))
			}
			return .Interface()
		}
	}

	// Populate Enum and Message.
	if .Enum() == nil && .Kind() == protoreflect.EnumKind {
		switch v := reflect.Zero().Interface().(type) {
		case protoreflect.Enum:
			.L1.Enum = .Descriptor()
		default:
			.L1.Enum = LegacyLoadEnumDesc()
		}
	}
	if .Message() == nil && (.Kind() == protoreflect.MessageKind || .Kind() == protoreflect.GroupKind) {
		switch v := reflect.Zero().Interface().(type) {
		case protoreflect.ProtoMessage:
			.L1.Message = .ProtoReflect().Descriptor()
		case messageV1:
			.L1.Message = LegacyLoadMessageDesc()
		default:
			if .Kind() == reflect.Map {
				 := len(.L1.Messages.List)
				.L1.Messages.List = append(.L1.Messages.List, filedesc.Message{L2: new(filedesc.MessageL2)})
				 := &.L1.Messages.List[]
				.L0.FullName = .FullName().Append(protoreflect.Name(strs.MapEntryName(string(.Name()))))
				.L0.ParentFile = .L0.ParentFile
				.L0.Parent = 
				.L0.Index = 

				.L1.IsMapEntry = true
				.L2.Options = func() protoreflect.ProtoMessage {
					 := descopts.Message.ProtoReflect().New()
					.Set(.Descriptor().Fields().ByName("map_entry"), protoreflect.ValueOfBool(true))
					return .Interface()
				}

				(, .Key(), , "", "")
				(, .Elem(), , "", "")

				.L1.Message = 
				break
			}
			.L1.Message = aberrantLoadMessageDescReentrant(, "")
		}
	}
}

type placeholderEnumValues struct {
	protoreflect.EnumValueDescriptors
}

func (placeholderEnumValues) ( protoreflect.EnumNumber) protoreflect.EnumValueDescriptor {
	return filedesc.PlaceholderEnumValue(protoreflect.FullName(fmt.Sprintf("UNKNOWN_%d", )))
}

// legacyMarshaler is the proto.Marshaler interface superseded by protoiface.Methoder.
type legacyMarshaler interface {
	Marshal() ([]byte, error)
}

// legacyUnmarshaler is the proto.Unmarshaler interface superseded by protoiface.Methoder.
type legacyUnmarshaler interface {
	Unmarshal([]byte) error
}

// legacyMerger is the proto.Merger interface superseded by protoiface.Methoder.
type legacyMerger interface {
	Merge(protoiface.MessageV1)
}

var aberrantProtoMethods = &protoiface.Methods{
	Marshal:   legacyMarshal,
	Unmarshal: legacyUnmarshal,
	Merge:     legacyMerge,

	// We have no way to tell whether the type's Marshal method
	// supports deterministic serialization or not, but this
	// preserves the v1 implementation's behavior of always
	// calling Marshal methods when present.
	Flags: protoiface.SupportMarshalDeterministic,
}

func ( protoiface.MarshalInput) (protoiface.MarshalOutput, error) {
	 := .Message.(unwrapper).protoUnwrap()
	,  := .(legacyMarshaler)
	if ! {
		return protoiface.MarshalOutput{}, errors.New("%T does not implement Marshal", )
	}
	,  := .Marshal()
	if .Buf != nil {
		 = append(.Buf, ...)
	}
	return protoiface.MarshalOutput{
		Buf: ,
	}, 
}

func ( protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) {
	 := .Message.(unwrapper).protoUnwrap()
	,  := .(legacyUnmarshaler)
	if ! {
		return protoiface.UnmarshalOutput{}, errors.New("%T does not implement Unmarshal", )
	}
	return protoiface.UnmarshalOutput{}, .Unmarshal(.Buf)
}

func ( protoiface.MergeInput) protoiface.MergeOutput {
	// Check whether this supports the legacy merger.
	 := .Destination.(unwrapper).protoUnwrap()
	,  := .(legacyMerger)
	if  {
		.Merge(Export{}.ProtoMessageV1Of(.Source))
		return protoiface.MergeOutput{Flags: protoiface.MergeComplete}
	}

	// If legacy merger is unavailable, implement merge in terms of
	// a marshal and unmarshal operation.
	 := .Source.(unwrapper).protoUnwrap()
	,  := .(legacyMarshaler)
	if ! {
		return protoiface.MergeOutput{}
	}
	 = .Destination.(unwrapper).protoUnwrap()
	,  := .(legacyUnmarshaler)
	if ! {
		return protoiface.MergeOutput{}
	}
	if !.Source.IsValid() {
		// Legacy Marshal methods may not function on nil messages.
		// Check for a typed nil source only after we confirm that
		// legacy Marshal/Unmarshal methods are present, for
		// consistency.
		return protoiface.MergeOutput{Flags: protoiface.MergeComplete}
	}
	,  := .Marshal()
	if  != nil {
		return protoiface.MergeOutput{}
	}
	 = .Unmarshal()
	if  != nil {
		return protoiface.MergeOutput{}
	}
	return protoiface.MergeOutput{Flags: protoiface.MergeComplete}
}

// aberrantMessageType implements MessageType for all types other than pointer-to-struct.
type aberrantMessageType struct {
	t reflect.Type
}

func ( aberrantMessageType) () protoreflect.Message {
	if .t.Kind() == reflect.Ptr {
		return aberrantMessage{reflect.New(.t.Elem())}
	}
	return aberrantMessage{reflect.Zero(.t)}
}
func ( aberrantMessageType) () protoreflect.Message {
	return aberrantMessage{reflect.Zero(.t)}
}
func ( aberrantMessageType) () reflect.Type {
	return .t
}
func ( aberrantMessageType) () protoreflect.MessageDescriptor {
	return LegacyLoadMessageDesc(.t)
}

// aberrantMessage implements Message for all types other than pointer-to-struct.
//
// When the underlying type implements legacyMarshaler or legacyUnmarshaler,
// the aberrant Message can be marshaled or unmarshaled. Otherwise, there is
// not much that can be done with values of this type.
type aberrantMessage struct {
	v reflect.Value
}

// Reset implements the v1 proto.Message.Reset method.
func ( aberrantMessage) () {
	if ,  := .v.Interface().(interface{ () });  {
		.()
		return
	}
	if .v.Kind() == reflect.Ptr && !.v.IsNil() {
		.v.Elem().Set(reflect.Zero(.v.Type().Elem()))
	}
}

func ( aberrantMessage) () protoreflect.Message {
	return 
}

func ( aberrantMessage) () protoreflect.MessageDescriptor {
	return LegacyLoadMessageDesc(.v.Type())
}
func ( aberrantMessage) () protoreflect.MessageType {
	return aberrantMessageType{.v.Type()}
}
func ( aberrantMessage) () protoreflect.Message {
	if .v.Type().Kind() == reflect.Ptr {
		return aberrantMessage{reflect.New(.v.Type().Elem())}
	}
	return aberrantMessage{reflect.Zero(.v.Type())}
}
func ( aberrantMessage) () protoreflect.ProtoMessage {
	return 
}
func ( aberrantMessage) ( func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
	return
}
func ( aberrantMessage) (protoreflect.FieldDescriptor) bool {
	return false
}
func ( aberrantMessage) (protoreflect.FieldDescriptor) {
	panic("invalid Message.Clear on " + string(.Descriptor().FullName()))
}
func ( aberrantMessage) ( protoreflect.FieldDescriptor) protoreflect.Value {
	if .Default().IsValid() {
		return .Default()
	}
	panic("invalid Message.Get on " + string(.Descriptor().FullName()))
}
func ( aberrantMessage) (protoreflect.FieldDescriptor, protoreflect.Value) {
	panic("invalid Message.Set on " + string(.Descriptor().FullName()))
}
func ( aberrantMessage) (protoreflect.FieldDescriptor) protoreflect.Value {
	panic("invalid Message.Mutable on " + string(.Descriptor().FullName()))
}
func ( aberrantMessage) (protoreflect.FieldDescriptor) protoreflect.Value {
	panic("invalid Message.NewField on " + string(.Descriptor().FullName()))
}
func ( aberrantMessage) (protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {
	panic("invalid Message.WhichOneof descriptor on " + string(.Descriptor().FullName()))
}
func ( aberrantMessage) () protoreflect.RawFields {
	return nil
}
func ( aberrantMessage) (protoreflect.RawFields) {
	// SetUnknown discards its input on messages which don't support unknown field storage.
}
func ( aberrantMessage) () bool {
	if .v.Kind() == reflect.Ptr {
		return !.v.IsNil()
	}
	return false
}
func ( aberrantMessage) () *protoiface.Methods {
	return aberrantProtoMethods
}
func ( aberrantMessage) () interface{} {
	return .v.Interface()
}