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

	
	
	
)

type reflectMessageInfo struct {
	fields map[protoreflect.FieldNumber]*fieldInfo
	oneofs map[protoreflect.Name]*oneofInfo

	// fieldTypes contains the zero value of an enum or message field.
	// For lists, it contains the element type.
	// For maps, it contains the entry value type.
	fieldTypes map[protoreflect.FieldNumber]interface{}

	// denseFields is a subset of fields where:
	//	0 < fieldDesc.Number() < len(denseFields)
	// It provides faster access to the fieldInfo, but may be incomplete.
	denseFields []*fieldInfo

	// rangeInfos is a list of all fields (not belonging to a oneof) and oneofs.
	rangeInfos []interface{} // either *fieldInfo or *oneofInfo

	getUnknown   func(pointer) protoreflect.RawFields
	setUnknown   func(pointer, protoreflect.RawFields)
	extensionMap func(pointer) *extensionMap

	nilMessage atomicNilMessage
}

// makeReflectFuncs generates the set of functions to support reflection.
func ( *MessageInfo) ( reflect.Type,  structInfo) {
	.makeKnownFieldsFunc()
	.makeUnknownFieldsFunc(, )
	.makeExtensionFieldsFunc(, )
	.makeFieldTypes()
}

// makeKnownFieldsFunc generates functions for operations that can be performed
// on each protobuf message field. It takes in a reflect.Type representing the
// Go struct and matches message fields with struct fields.
//
// This code assumes that the struct is well-formed and panics if there are
// any discrepancies.
func ( *MessageInfo) ( structInfo) {
	.fields = map[protoreflect.FieldNumber]*fieldInfo{}
	 := .Desc
	 := .Fields()
	for  := 0;  < .Len(); ++ {
		 := .Get()
		 := .fieldsByNumber[.Number()]
		 := .ContainingOneof() != nil && !.ContainingOneof().IsSynthetic()
		if  {
			 = .oneofsByName[.ContainingOneof().Name()]
		}
		var  fieldInfo
		switch {
		case .Type == nil:
			 = fieldInfoForMissing() // never occurs for officially generated message types
		case :
			 = fieldInfoForOneof(, , .Exporter, .oneofWrappersByNumber[.Number()])
		case .IsMap():
			 = fieldInfoForMap(, , .Exporter)
		case .IsList():
			 = fieldInfoForList(, , .Exporter)
		case .IsWeak():
			 = fieldInfoForWeakMessage(, .weakOffset)
		case .Message() != nil:
			 = fieldInfoForMessage(, , .Exporter)
		default:
			 = fieldInfoForScalar(, , .Exporter)
		}
		.fields[.Number()] = &
	}

	.oneofs = map[protoreflect.Name]*oneofInfo{}
	for  := 0;  < .Oneofs().Len(); ++ {
		 := .Oneofs().Get()
		.oneofs[.Name()] = makeOneofInfo(, , .Exporter)
	}

	.denseFields = make([]*fieldInfo, .Len()*2)
	for  := 0;  < .Len(); ++ {
		if  := .Get(); int(.Number()) < len(.denseFields) {
			.denseFields[.Number()] = .fields[.Number()]
		}
	}

	for  := 0;  < .Len(); {
		 := .Get()
		if  := .ContainingOneof();  != nil && !.IsSynthetic() {
			.rangeInfos = append(.rangeInfos, .oneofs[.Name()])
			 += .Fields().Len()
		} else {
			.rangeInfos = append(.rangeInfos, .fields[.Number()])
			++
		}
	}

	// Introduce instability to iteration order, but keep it deterministic.
	if len(.rangeInfos) > 1 && detrand.Bool() {
		 := detrand.Intn(len(.rangeInfos) - 1)
		.rangeInfos[], .rangeInfos[+1] = .rangeInfos[+1], .rangeInfos[]
	}
}

func ( *MessageInfo) ( reflect.Type,  structInfo) {
	switch {
	case .unknownOffset.IsValid() && .unknownType == unknownFieldsAType:
		// Handle as []byte.
		.getUnknown = func( pointer) protoreflect.RawFields {
			if .IsNil() {
				return nil
			}
			return *.Apply(.unknownOffset).Bytes()
		}
		.setUnknown = func( pointer,  protoreflect.RawFields) {
			if .IsNil() {
				panic("invalid SetUnknown on nil Message")
			}
			*.Apply(.unknownOffset).Bytes() = 
		}
	case .unknownOffset.IsValid() && .unknownType == unknownFieldsBType:
		// Handle as *[]byte.
		.getUnknown = func( pointer) protoreflect.RawFields {
			if .IsNil() {
				return nil
			}
			 := .Apply(.unknownOffset).BytesPtr()
			if * == nil {
				return nil
			}
			return **
		}
		.setUnknown = func( pointer,  protoreflect.RawFields) {
			if .IsNil() {
				panic("invalid SetUnknown on nil Message")
			}
			 := .Apply(.unknownOffset).BytesPtr()
			if * == nil {
				* = new([]byte)
			}
			** = 
		}
	default:
		.getUnknown = func(pointer) protoreflect.RawFields {
			return nil
		}
		.setUnknown = func( pointer,  protoreflect.RawFields) {
			if .IsNil() {
				panic("invalid SetUnknown on nil Message")
			}
		}
	}
}

func ( *MessageInfo) ( reflect.Type,  structInfo) {
	if .extensionOffset.IsValid() {
		.extensionMap = func( pointer) *extensionMap {
			if .IsNil() {
				return (*extensionMap)(nil)
			}
			 := .Apply(.extensionOffset).AsValueOf(extensionFieldsType)
			return (*extensionMap)(.Interface().(*map[int32]ExtensionField))
		}
	} else {
		.extensionMap = func(pointer) *extensionMap {
			return (*extensionMap)(nil)
		}
	}
}
func ( *MessageInfo) ( structInfo) {
	 := .Desc
	 := .Fields()
	for  := 0;  < .Len(); ++ {
		var  reflect.Type
		 := .Get()
		 := .fieldsByNumber[.Number()]
		 := .ContainingOneof() != nil && !.ContainingOneof().IsSynthetic()
		if  {
			 = .oneofsByName[.ContainingOneof().Name()]
		}
		var  bool
		switch {
		case .Type == nil:
			continue // never occurs for officially generated message types
		case :
			if .Enum() != nil || .Message() != nil {
				 = .oneofWrappersByNumber[.Number()].Field(0).Type
			}
		case .IsMap():
			if .MapValue().Enum() != nil || .MapValue().Message() != nil {
				 = .Type.Elem()
			}
			 = .MapValue().Message() != nil
		case .IsList():
			if .Enum() != nil || .Message() != nil {
				 = .Type.Elem()
			}
			 = .Message() != nil
		case .Enum() != nil:
			 = .Type
			if .HasPresence() && .Kind() == reflect.Ptr {
				 = .Elem()
			}
		case .Message() != nil:
			 = .Type
			if .IsWeak() {
				 = nil
			}
			 = true
		}
		if  &&  != nil && .Kind() != reflect.Ptr {
			 = reflect.PtrTo() // never occurs for officially generated message types
		}
		if  != nil {
			if .fieldTypes == nil {
				.fieldTypes = make(map[protoreflect.FieldNumber]interface{})
			}
			.fieldTypes[.Number()] = reflect.Zero().Interface()
		}
	}
}

type extensionMap map[int32]ExtensionField

func ( *extensionMap) ( func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
	if  != nil {
		for ,  := range * {
			 := .Type().TypeDescriptor()
			 := .Value()
			if .IsList() && .List().Len() == 0 {
				continue
			}
			if !(, ) {
				return
			}
		}
	}
}
func ( *extensionMap) ( protoreflect.ExtensionType) ( bool) {
	if  == nil {
		return false
	}
	 := .TypeDescriptor()
	,  := (*)[int32(.Number())]
	if ! {
		return false
	}
	switch {
	case .IsList():
		return .Value().List().Len() > 0
	case .IsMap():
		return .Value().Map().Len() > 0
	case .Message() != nil:
		return .Value().Message().IsValid()
	}
	return true
}
func ( *extensionMap) ( protoreflect.ExtensionType) {
	delete(*, int32(.TypeDescriptor().Number()))
}
func ( *extensionMap) ( protoreflect.ExtensionType) protoreflect.Value {
	 := .TypeDescriptor()
	if  != nil {
		if ,  := (*)[int32(.Number())];  {
			return .Value()
		}
	}
	return .Zero()
}
func ( *extensionMap) ( protoreflect.ExtensionType,  protoreflect.Value) {
	 := .TypeDescriptor()
	 := true
	switch {
	case !.IsValidValue():
		 = false
	case .IsList():
		 = .List().IsValid()
	case .IsMap():
		 = .Map().IsValid()
	case .Message() != nil:
		 = .Message().IsValid()
	}
	if ! {
		panic(fmt.Sprintf("%v: assigning invalid value", .TypeDescriptor().FullName()))
	}

	if * == nil {
		* = make(map[int32]ExtensionField)
	}
	var  ExtensionField
	.Set(, )
	(*)[int32(.Number())] = 
}
func ( *extensionMap) ( protoreflect.ExtensionType) protoreflect.Value {
	 := .TypeDescriptor()
	if .Kind() != protoreflect.MessageKind && .Kind() != protoreflect.GroupKind && !.IsList() && !.IsMap() {
		panic("invalid Mutable on field with non-composite type")
	}
	if ,  := (*)[int32(.Number())];  {
		return .Value()
	}
	 := .New()
	.Set(, )
	return 
}

// MessageState is a data structure that is nested as the first field in a
// concrete message. It provides a way to implement the ProtoReflect method
// in an allocation-free way without needing to have a shadow Go type generated
// for every message type. This technique only works using unsafe.
//
// Example generated code:
//
//	type M struct {
//		state protoimpl.MessageState
//
//		Field1 int32
//		Field2 string
//		Field3 *BarMessage
//		...
//	}
//
//	func (m *M) ProtoReflect() protoreflect.Message {
//		mi := &file_fizz_buzz_proto_msgInfos[5]
//		if protoimpl.UnsafeEnabled && m != nil {
//			ms := protoimpl.X.MessageStateOf(Pointer(m))
//			if ms.LoadMessageInfo() == nil {
//				ms.StoreMessageInfo(mi)
//			}
//			return ms
//		}
//		return mi.MessageOf(m)
//	}
//
// The MessageState type holds a *MessageInfo, which must be atomically set to
// the message info associated with a given message instance.
// By unsafely converting a *M into a *MessageState, the MessageState object
// has access to all the information needed to implement protobuf reflection.
// It has access to the message info as its first field, and a pointer to the
// MessageState is identical to a pointer to the concrete message value.
//
// Requirements:
//   - The type M must implement protoreflect.ProtoMessage.
//   - The address of m must not be nil.
//   - The address of m and the address of m.state must be equal,
//     even though they are different Go types.
type MessageState struct {
	pragma.NoUnkeyedLiterals
	pragma.DoNotCompare
	pragma.DoNotCopy

	atomicMessageInfo *MessageInfo
}

type messageState MessageState

var (
	_ protoreflect.Message = (*messageState)(nil)
	_ unwrapper            = (*messageState)(nil)
)

// messageDataType is a tuple of a pointer to the message data and
// a pointer to the message type. It is a generalized way of providing a
// reflective view over a message instance. The disadvantage of this approach
// is the need to allocate this tuple of 16B.
type messageDataType struct {
	p  pointer
	mi *MessageInfo
}

type (
	messageReflectWrapper messageDataType
	messageIfaceWrapper   messageDataType
)

var (
	_ protoreflect.Message      = (*messageReflectWrapper)(nil)
	_ unwrapper                 = (*messageReflectWrapper)(nil)
	_ protoreflect.ProtoMessage = (*messageIfaceWrapper)(nil)
	_ unwrapper                 = (*messageIfaceWrapper)(nil)
)

// MessageOf returns a reflective view over a message. The input must be a
// pointer to a named Go struct. If the provided type has a ProtoReflect method,
// it must be implemented by calling this method.
func ( *MessageInfo) ( interface{}) protoreflect.Message {
	if reflect.TypeOf() != .GoReflectType {
		panic(fmt.Sprintf("type mismatch: got %T, want %v", , .GoReflectType))
	}
	 := pointerOfIface()
	if .IsNil() {
		return .nilMessage.Init()
	}
	return &messageReflectWrapper{, }
}

func ( *messageReflectWrapper) () pointer          { return .p }
func ( *messageReflectWrapper) () *MessageInfo { return .mi }

// Reset implements the v1 proto.Message.Reset method.
func ( *messageIfaceWrapper) () {
	if ,  := .protoUnwrap().(interface{ () });  {
		.()
		return
	}
	 := reflect.ValueOf(.protoUnwrap())
	if .Kind() == reflect.Ptr && !.IsNil() {
		.Elem().Set(reflect.Zero(.Type().Elem()))
	}
}
func ( *messageIfaceWrapper) () protoreflect.Message {
	return (*messageReflectWrapper)()
}
func ( *messageIfaceWrapper) () interface{} {
	return .p.AsIfaceOf(.mi.GoReflectType.Elem())
}

// checkField verifies that the provided field descriptor is valid.
// Exactly one of the returned values is populated.
func ( *MessageInfo) ( protoreflect.FieldDescriptor) (*fieldInfo, protoreflect.ExtensionType) {
	var  *fieldInfo
	if  := .Number(); 0 <  && int() < len(.denseFields) {
		 = .denseFields[]
	} else {
		 = .fields[]
	}
	if  != nil {
		if .fieldDesc !=  {
			if ,  := .FullName(), .fieldDesc.FullName();  !=  {
				panic(fmt.Sprintf("mismatching field: got %v, want %v", , ))
			}
			panic(fmt.Sprintf("mismatching field: %v", .FullName()))
		}
		return , nil
	}

	if .IsExtension() {
		if ,  := .ContainingMessage().FullName(), .Desc.FullName();  !=  {
			// TODO: Should this be exact containing message descriptor match?
			panic(fmt.Sprintf("extension %v has mismatching containing message: got %v, want %v", .FullName(), , ))
		}
		if !.Desc.ExtensionRanges().Has(.Number()) {
			panic(fmt.Sprintf("extension %v extends %v outside the extension range", .FullName(), .Desc.FullName()))
		}
		,  := .(protoreflect.ExtensionTypeDescriptor)
		if ! {
			panic(fmt.Sprintf("extension %v does not implement protoreflect.ExtensionTypeDescriptor", .FullName()))
		}
		return nil, .Type()
	}
	panic(fmt.Sprintf("field %v is invalid", .FullName()))
}