Skip to content

Commit

Permalink
Merge pull request #188 from mercari/fix-enum-conversion
Browse files Browse the repository at this point in the history
Fix auto enum conversion for request
  • Loading branch information
goccy authored Jun 3, 2024
2 parents ffd321c + 1b5b030 commit a9598c9
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 29 deletions.
60 changes: 49 additions & 11 deletions generator/code_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -1695,15 +1695,15 @@ type CastEnumValue struct {
ToValue string
}

func (f *CastField) ToEnum() *CastEnum {
func (f *CastField) ToEnum() (*CastEnum, error) {
toEnum := f.toType.Enum
if toEnum.Rule != nil && len(toEnum.Rule.Aliases) != 0 {
return f.toEnumByAlias(toEnum, f.fromType.Enum)
return f.toEnumFromDepServiceToService(toEnum, f.fromType.Enum), nil
}
fromEnum := f.fromType.Enum
if fromEnum.Rule != nil && len(fromEnum.Rule.Aliases) != 0 {
// the type conversion is performed at the time of gRPC method call.
return f.toEnumByAlias(fromEnum, f.toType.Enum)
return f.toEnumFromServiceToDepService(fromEnum, f.toType.Enum)
}
toEnumName := toEnumValuePrefix(f.file, f.toType)
fromEnumName := toEnumValuePrefix(f.file, f.fromType)
Expand All @@ -1724,33 +1724,35 @@ func (f *CastField) ToEnum() *CastEnum {
return &CastEnum{
FromValues: enumValues,
DefaultValue: "0",
}
}, nil
}

func (f *CastField) toEnumByAlias(enum, aliasEnum *resolver.Enum) *CastEnum {
toEnumName := toEnumValuePrefix(f.file, f.toType)
fromEnumName := toEnumValuePrefix(f.file, f.fromType)
// toEnumFromDepServiceToService converts dependent service's enum type to our service's enum type.
// alias is defined for dependent service.
func (f *CastField) toEnumFromDepServiceToService(enum, depSvcEnum *resolver.Enum) *CastEnum {
var (
enumValues []*CastEnumValue
defaultValue = "0"
)
svcEnumName := toEnumValuePrefix(f.file, f.toType)
depSvcEnumName := toEnumValuePrefix(f.file, f.fromType)
for _, value := range enum.Values {
if value.Rule == nil {
continue
}
for _, enumValueAlias := range value.Rule.Aliases {
if enumValueAlias.EnumAlias != aliasEnum {
if enumValueAlias.EnumAlias != depSvcEnum {
continue
}
for _, alias := range enumValueAlias.Aliases {
enumValues = append(enumValues, &CastEnumValue{
FromValue: toEnumValueText(fromEnumName, alias.Value),
ToValue: toEnumValueText(toEnumName, value.Value),
FromValue: toEnumValueText(depSvcEnumName, alias.Value),
ToValue: toEnumValueText(svcEnumName, value.Value),
})
}
}
if value.Rule.Default {
defaultValue = toEnumValueText(toEnumName, value.Value)
defaultValue = toEnumValueText(svcEnumName, value.Value)
}
}
return &CastEnum{
Expand All @@ -1759,6 +1761,42 @@ func (f *CastField) toEnumByAlias(enum, aliasEnum *resolver.Enum) *CastEnum {
}
}

// toEnumFromServiceToDepService converts our service's enum type to dependent service's enum type.
// alias is defined for dependent service.
func (f *CastField) toEnumFromServiceToDepService(enum, depSvcEnum *resolver.Enum) (*CastEnum, error) {
var (
enumValues []*CastEnumValue
defaultValue = "0"
)
depSvcEnumName := toEnumValuePrefix(f.file, f.toType)
svcEnumName := toEnumValuePrefix(f.file, f.fromType)
for _, value := range enum.Values {
if value.Rule == nil {
continue
}
for _, enumValueAlias := range value.Rule.Aliases {
if enumValueAlias.EnumAlias != depSvcEnum {
continue
}
if len(enumValueAlias.Aliases) != 1 {
return nil, fmt.Errorf("found multiple aliases are set. the conversion destination cannot be uniquely determined")
}
depEnumValue := enumValueAlias.Aliases[0]
enumValues = append(enumValues, &CastEnumValue{
FromValue: toEnumValueText(svcEnumName, value.Value),
ToValue: toEnumValueText(depSvcEnumName, depEnumValue.Value),
})
}
if value.Rule.Default {
return nil, fmt.Errorf("found default alias is set. the conversion destination cannot be uniquely determined")
}
}
return &CastEnum{
FromValues: enumValues,
DefaultValue: defaultValue,
}, nil
}

type CastSlice struct {
ResponseType string
ElemRequiredCast bool
Expand Down
22 changes: 11 additions & 11 deletions generator/testdata/expected_create_post.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions resolver/resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,15 +541,15 @@ func TestCreatePost(t *testing.T) {
testutil.NewEnumBuilder("PostType").
WithAlias(ref.Enum(t, "org.post", "PostType")).
AddValueWithAlias(
"POST_TYPE_UNKNOWN",
"TYPE_UNKNOWN",
ref.EnumValue(t, "org.post", "PostType", "POST_TYPE_UNKNOWN"),
).
AddValueWithAlias(
"POST_TYPE_A",
"TYPE_A",
ref.EnumValue(t, "org.post", "PostType", "POST_TYPE_A"),
).
AddValueWithAlias(
"POST_TYPE_B",
"TYPE_B",
ref.EnumValue(t, "org.post", "PostType", "POST_TYPE_B"),
).
Build(t),
Expand Down
8 changes: 4 additions & 4 deletions testdata/create_post.proto
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ service FederationService {
enum PostType {
option (grpc.federation.enum).alias = "org.post.PostType";

POST_TYPE_UNKNOWN = 0;
POST_TYPE_A = 1;
POST_TYPE_B = 2;
TYPE_UNKNOWN = 0 [(grpc.federation.enum_value).alias = "POST_TYPE_UNKNOWN"];
TYPE_A = 1 [(grpc.federation.enum_value).alias = "POST_TYPE_A"];
TYPE_B = 2 [(grpc.federation.enum_value).alias = "POST_TYPE_B"];
}

message CreatePostRequest {
Expand Down Expand Up @@ -62,7 +62,7 @@ message CreatePost {
string content = 2 [(grpc.federation.field).by = "$.content"];
string user_id = 3 [(grpc.federation.field).by = "$.user_id"];
PostType type = 4 [(grpc.federation.field).by = "$.type"];
PostType post_type = 5 [(grpc.federation.field).by = "org.federation.PostType.POST_TYPE_A"];
PostType post_type = 5 [(grpc.federation.field).by = "org.federation.PostType.TYPE_A"];
}

message Post {
Expand Down

0 comments on commit a9598c9

Please sign in to comment.