Skip to content

Commit

Permalink
Merge pull request grpc-ecosystem#315 from nilium/fix-query-param-enums
Browse files Browse the repository at this point in the history
Look up enum value maps by their proto name
  • Loading branch information
tmc authored Feb 24, 2017
2 parents 43f0129 + 4d319d2 commit 6b88bed
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 16 deletions.
22 changes: 12 additions & 10 deletions runtime/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ func populateFieldValueFromPath(msg proto.Message, fieldPath []string, values []
if m.Kind() != reflect.Ptr {
return fmt.Errorf("unexpected type %T: %v", msg, msg)
}
var props *proto.Properties
m = m.Elem()
for i, fieldName := range fieldPath {
isLast := i == len(fieldPath)-1
if !isLast && m.Kind() != reflect.Struct {
return fmt.Errorf("non-aggregate type in the mid of path: %s", strings.Join(fieldPath, "."))
}
f := fieldByProtoName(m, fieldName)
var f reflect.Value
f, props = fieldByProtoName(m, fieldName)
if !f.IsValid() {
grpclog.Printf("field not found in %T: %s", msg, strings.Join(fieldPath, "."))
return nil
Expand All @@ -60,7 +62,7 @@ func populateFieldValueFromPath(msg proto.Message, fieldPath []string, values []
if !isLast {
return fmt.Errorf("unexpected repeated field in %s", strings.Join(fieldPath, "."))
}
return populateRepeatedField(f, values)
return populateRepeatedField(f, values, props)
case reflect.Ptr:
if f.IsNil() {
m = reflect.New(f.Type().Elem())
Expand All @@ -82,26 +84,26 @@ func populateFieldValueFromPath(msg proto.Message, fieldPath []string, values []
default:
grpclog.Printf("too many field values: %s", strings.Join(fieldPath, "."))
}
return populateField(m, values[0])
return populateField(m, values[0], props)
}

// fieldByProtoName looks up a field whose corresponding protobuf field name is "name".
// "m" must be a struct value. It returns zero reflect.Value if no such field found.
func fieldByProtoName(m reflect.Value, name string) reflect.Value {
func fieldByProtoName(m reflect.Value, name string) (reflect.Value, *proto.Properties) {
props := proto.GetProperties(m.Type())
for _, p := range props.Prop {
if p.OrigName == name {
return m.FieldByName(p.Name)
return m.FieldByName(p.Name), p
}
}
return reflect.Value{}
return reflect.Value{}, nil
}

func populateRepeatedField(f reflect.Value, values []string) error {
func populateRepeatedField(f reflect.Value, values []string, props *proto.Properties) error {
elemType := f.Type().Elem()

// is the destination field a slice of an enumeration type?
if enumValMap := proto.EnumValueMap(elemType.String()); enumValMap != nil {
if enumValMap := proto.EnumValueMap(props.Enum); enumValMap != nil {
return populateFieldEnumRepeated(f, values, enumValMap)
}

Expand All @@ -120,7 +122,7 @@ func populateRepeatedField(f reflect.Value, values []string) error {
return nil
}

func populateField(f reflect.Value, value string) error {
func populateField(f reflect.Value, value string, props *proto.Properties) error {
// Handle well known type
type wkt interface {
XXX_WellKnownType() string
Expand All @@ -145,7 +147,7 @@ func populateField(f reflect.Value, value string) error {
}

// is the destination field an enumeration type?
if enumValMap := proto.EnumValueMap(f.Type().String()); enumValMap != nil {
if enumValMap := proto.EnumValueMap(props.Enum); enumValMap != nil {
return populateFieldEnum(f, value, enumValMap)
}

Expand Down
12 changes: 6 additions & 6 deletions runtime/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func TestPopulateParameters(t *testing.T) {
msg.Reset()
err := runtime.PopulateQueryParameters(msg, spec.values, spec.filter)
if err != nil {
t.Errorf("runtime.PoplateQueryParameters(msg, %v, %v) failed with %v; want success", spec.values, spec.filter, err)
t.Errorf("runtime.PopulateQueryParameters(msg, %v, %v) failed with %v; want success", spec.values, spec.filter, err)
continue
}
if got, want := msg, spec.want; !proto.Equal(got, want) {
Expand Down Expand Up @@ -241,8 +241,8 @@ type proto3Message struct {
BoolValue bool `protobuf:"varint,8,opt,name=bool_value" json:"bool_value,omitempty"`
StringValue string `protobuf:"bytes,9,opt,name=string_value" json:"string_value,omitempty"`
RepeatedValue []string `protobuf:"bytes,10,rep,name=repeated_value" json:"repeated_value,omitempty"`
EnumValue EnumValue `protobuf:"varint,11,opt,name=enum_value,json=enumValue,enum=api.EnumValue" json:"enum_value,omitempty"`
RepeatedEnum []EnumValue `protobuf:"varint,12,rep,packed,name=repeated_enum,json=repeated_enum,enum=api.EnumValue" json:"repeated_enum,omitempty"`
EnumValue EnumValue `protobuf:"varint,11,opt,name=enum_value,json=enumValue,enum=runtime_test_api.EnumValue" json:"enum_value,omitempty"`
RepeatedEnum []EnumValue `protobuf:"varint,12,rep,packed,name=repeated_enum,json=repeated_enum,enum=runtime_test_api.EnumValue" json:"repeated_enum,omitempty"`
TimestampValue *timestamp.Timestamp `protobuf:"bytes,11,opt,name=timestamp_value" json:"timestamp_value,omitempty"`
}

Expand All @@ -268,8 +268,8 @@ type proto2Message struct {
BoolValue *bool `protobuf:"varint,8,opt,name=bool_value" json:"bool_value,omitempty"`
StringValue *string `protobuf:"bytes,9,opt,name=string_value" json:"string_value,omitempty"`
RepeatedValue []string `protobuf:"bytes,10,rep,name=repeated_value" json:"repeated_value,omitempty"`
EnumValue EnumValue `protobuf:"varint,11,opt,name=enum_value,json=enumValue,enum=api.EnumValue" json:"enum_value,omitempty"`
RepeatedEnum []EnumValue `protobuf:"varint,12,rep,packed,name=repeated_enum,json=repeated_enum,enum=api.EnumValue" json:"repeated_enum,omitempty"`
EnumValue EnumValue `protobuf:"varint,11,opt,name=enum_value,json=enumValue,enum=runtime_test_api.EnumValue" json:"enum_value,omitempty"`
RepeatedEnum []EnumValue `protobuf:"varint,12,rep,packed,name=repeated_enum,json=repeated_enum,enum=runtime_test_api.EnumValue" json:"repeated_enum,omitempty"`
XXX_unrecognized []byte `json:"-"`
}

Expand Down Expand Up @@ -367,5 +367,5 @@ var EnumValue_value = map[string]int32{
}

func init() {
proto.RegisterEnum("runtime_test.EnumValue", EnumValue_name, EnumValue_value)
proto.RegisterEnum("runtime_test_api.EnumValue", EnumValue_name, EnumValue_value)
}

0 comments on commit 6b88bed

Please sign in to comment.