func newProperties()

in proto/properties.go [227:302]


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

	var hasOneof bool
	prop := new(StructProperties)

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

		tagOneof := f.Tag.Get("protobuf_oneof")
		if tagOneof != "" {
			hasOneof = true
			p.OrigName = tagOneof
		}

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

		prop.Prop = append(prop.Prop, p)
	}

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

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

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

	return prop
}