// Copyright 2010 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 proto

import (
	
	
	
	
	

	
	
)

// StructProperties represents protocol buffer type information for a
// generated protobuf message in the open-struct API.
//
// Deprecated: Do not use.
type StructProperties struct {
	// Prop are the properties for each field.
	//
	// Fields belonging to a oneof are stored in OneofTypes instead, with a
	// single Properties representing the parent oneof held here.
	//
	// The order of Prop matches the order of fields in the Go struct.
	// Struct fields that are not related to protobufs have a "XXX_" prefix
	// in the Properties.Name and must be ignored by the user.
	Prop []*Properties

	// OneofTypes contains information about the oneof fields in this message.
	// It is keyed by the protobuf field name.
	OneofTypes map[string]*OneofProperties
}

// Properties represents the type information for a protobuf message field.
//
// Deprecated: Do not use.
type Properties struct {
	// Name is a placeholder name with little meaningful semantic value.
	// If the name has an "XXX_" prefix, the entire Properties must be ignored.
	Name string
	// OrigName is the protobuf field name or oneof name.
	OrigName string
	// JSONName is the JSON name for the protobuf field.
	JSONName string
	// Enum is a placeholder name for enums.
	// For historical reasons, this is neither the Go name for the enum,
	// nor the protobuf name for the enum.
	Enum string // Deprecated: Do not use.
	// Weak contains the full name of the weakly referenced message.
	Weak string
	// Wire is a string representation of the wire type.
	Wire string
	// WireType is the protobuf wire type for the field.
	WireType int
	// Tag is the protobuf field number.
	Tag int
	// Required reports whether this is a required field.
	Required bool
	// Optional reports whether this is a optional field.
	Optional bool
	// Repeated reports whether this is a repeated field.
	Repeated bool
	// Packed reports whether this is a packed repeated field of scalars.
	Packed bool
	// Proto3 reports whether this field operates under the proto3 syntax.
	Proto3 bool
	// Oneof reports whether this field belongs within a oneof.
	Oneof bool

	// Default is the default value in string form.
	Default string
	// HasDefault reports whether the field has a default value.
	HasDefault bool

	// MapKeyProp is the properties for the key field for a map field.
	MapKeyProp *Properties
	// MapValProp is the properties for the value field for a map field.
	MapValProp *Properties
}

// OneofProperties represents the type information for a protobuf oneof.
//
// Deprecated: Do not use.
type OneofProperties struct {
	// Type is a pointer to the generated wrapper type for the field value.
	// This is nil for messages that are not in the open-struct API.
	Type reflect.Type
	// Field is the index into StructProperties.Prop for the containing oneof.
	Field int
	// Prop is the properties for the field.
	Prop *Properties
}

// String formats the properties in the protobuf struct field tag style.
func ( *Properties) () string {
	 := .Wire
	 += "," + strconv.Itoa(.Tag)
	if .Required {
		 += ",req"
	}
	if .Optional {
		 += ",opt"
	}
	if .Repeated {
		 += ",rep"
	}
	if .Packed {
		 += ",packed"
	}
	 += ",name=" + .OrigName
	if .JSONName != "" {
		 += ",json=" + .JSONName
	}
	if len(.Enum) > 0 {
		 += ",enum=" + .Enum
	}
	if len(.Weak) > 0 {
		 += ",weak=" + .Weak
	}
	if .Proto3 {
		 += ",proto3"
	}
	if .Oneof {
		 += ",oneof"
	}
	if .HasDefault {
		 += ",def=" + .Default
	}
	return 
}

// Parse populates p by parsing a string in the protobuf struct field tag style.
func ( *Properties) ( string) {
	// For example: "bytes,49,opt,name=foo,def=hello!"
	for len() > 0 {
		 := strings.IndexByte(, ',')
		if  < 0 {
			 = len()
		}
		switch  := [:]; {
		case strings.HasPrefix(, "name="):
			.OrigName = [len("name="):]
		case strings.HasPrefix(, "json="):
			.JSONName = [len("json="):]
		case strings.HasPrefix(, "enum="):
			.Enum = [len("enum="):]
		case strings.HasPrefix(, "weak="):
			.Weak = [len("weak="):]
		case strings.Trim(, "0123456789") == "":
			,  := strconv.ParseUint(, 10, 32)
			.Tag = int()
		case  == "opt":
			.Optional = true
		case  == "req":
			.Required = true
		case  == "rep":
			.Repeated = true
		case  == "varint" ||  == "zigzag32" ||  == "zigzag64":
			.Wire = 
			.WireType = WireVarint
		case  == "fixed32":
			.Wire = 
			.WireType = WireFixed32
		case  == "fixed64":
			.Wire = 
			.WireType = WireFixed64
		case  == "bytes":
			.Wire = 
			.WireType = WireBytes
		case  == "group":
			.Wire = 
			.WireType = WireStartGroup
		case  == "packed":
			.Packed = true
		case  == "proto3":
			.Proto3 = true
		case  == "oneof":
			.Oneof = true
		case strings.HasPrefix(, "def="):
			// The default tag is special in that everything afterwards is the
			// default regardless of the presence of commas.
			.HasDefault = true
			.Default,  = [len("def="):], len()
		}
		 = strings.TrimPrefix([:], ",")
	}
}

// Init populates the properties from a protocol buffer struct tag.
//
// Deprecated: Do not use.
func ( *Properties) ( reflect.Type, ,  string,  *reflect.StructField) {
	.Name = 
	.OrigName = 
	if  == "" {
		return
	}
	.Parse()

	if  != nil && .Kind() == reflect.Map {
		.MapKeyProp = new(Properties)
		.MapKeyProp.(nil, "Key", .Tag.Get("protobuf_key"), nil)
		.MapValProp = new(Properties)
		.MapValProp.(nil, "Value", .Tag.Get("protobuf_val"), nil)
	}
}

var propertiesCache sync.Map // map[reflect.Type]*StructProperties

// GetProperties returns the list of properties for the type represented by t,
// which must be a generated protocol buffer message in the open-struct API,
// where protobuf message fields are represented by exported Go struct fields.
//
// Deprecated: Use protobuf reflection instead.
func ( reflect.Type) *StructProperties {
	if ,  := propertiesCache.Load();  {
		return .(*StructProperties)
	}
	,  := propertiesCache.LoadOrStore(, newProperties())
	return .(*StructProperties)
}

func ( reflect.Type) *StructProperties {
	if .Kind() != reflect.Struct {
		panic(fmt.Sprintf("%v is not a generated message in the open-struct API", ))
	}

	var  bool
	 := new(StructProperties)

	// Construct a list of properties for each field in the struct.
	for  := 0;  < .NumField(); ++ {
		 := new(Properties)
		 := .Field()
		 := .Tag.Get("protobuf")
		.Init(.Type, .Name, , &)

		 := .Tag.Get("protobuf_oneof")
		if  != "" {
			 = true
			.OrigName = 
		}

		// Rename unrelated struct fields with the "XXX_" prefix since so much
		// user code simply checks for this to exclude special fields.
		if  == "" &&  == "" && !strings.HasPrefix(.Name, "XXX_") {
			.Name = "XXX_" + .Name
			.OrigName = "XXX_" + .OrigName
		} else if .Weak != "" {
			.Name = .OrigName // avoid possible "XXX_" prefix on weak field
		}

		.Prop = append(.Prop, )
	}

	// Construct a mapping of oneof field names to properties.
	if  {
		var  []interface{}
		if ,  := reflect.PtrTo().MethodByName("XXX_OneofFuncs");  {
			 = .Func.Call([]reflect.Value{reflect.Zero(.Type.In(0))})[3].Interface().([]interface{})
		}
		if ,  := reflect.PtrTo().MethodByName("XXX_OneofWrappers");  {
			 = .Func.Call([]reflect.Value{reflect.Zero(.Type.In(0))})[0].Interface().([]interface{})
		}
		if ,  := reflect.Zero(reflect.PtrTo()).Interface().(protoreflect.ProtoMessage);  {
			if ,  := .ProtoReflect().(interface{ () *protoimpl.MessageInfo });  {
				 = .().OneofWrappers
			}
		}

		.OneofTypes = make(map[string]*OneofProperties)
		for ,  := range  {
			 := &OneofProperties{
				Type: reflect.ValueOf().Type(), // *T
				Prop: new(Properties),
			}
			 := .Type.Elem().Field(0)
			.Prop.Name = .Name
			.Prop.Parse(.Tag.Get("protobuf"))

			// Determine the struct field that contains this oneof.
			// Each wrapper is assignable to exactly one parent field.
			var  bool
			for  := 0;  < .NumField() && !; ++ {
				if .Type.AssignableTo(.Field().Type) {
					.Field = 
					 = true
				}
			}
			if ! {
				panic(fmt.Sprintf("%v is not a generated message in the open-struct API", ))
			}
			.OneofTypes[.Prop.OrigName] = 
		}
	}

	return 
}

func ( *StructProperties) () int           { return len(.Prop) }
func ( *StructProperties) (,  int) bool { return false }
func ( *StructProperties) (,  int)      { return }