Skip to content

Commit

Permalink
Fix support for repeated enums inclusion check
Browse files Browse the repository at this point in the history
Generate code for C++ and Go for repeated.items.enum.{in, not_in}
validations, and add test cases. Fixes bufbuild#329

Signed-off-by: Alex Konradi <akonradi@google.com>
  • Loading branch information
akonradi committed Apr 14, 2020
1 parent 0f2bc6c commit 88233f7
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 2 deletions.
4 changes: 2 additions & 2 deletions templates/cc/in.go
Expand Up @@ -2,11 +2,11 @@ package cc

const inTpl = `{{ $f := .Field -}}{{ $r := .Rules -}}
{{- if $r.In }}
if ({{ lookup $f "InLookup" }}.find({{ accessor . }}) == {{ lookup $f "InLookup" }}.end()) {
if ({{ lookup $f "InLookup" }}.find(static_cast<decltype({{ lookup $f "InLookup" }})::key_type>({{ accessor . }})) == {{ lookup $f "InLookup" }}.end()) {
{{ err . "value must be in list " $r.In }}
}
{{- else if $r.NotIn }}
if ({{ lookup $f "NotInLookup" }}.find({{ accessor . }}) != {{ lookup $f "NotInLookup" }}.end()) {
if ({{ lookup $f "NotInLookup" }}.find(static_cast<decltype({{ lookup $f "NotInLookup" }})::key_type>({{ accessor . }})) != {{ lookup $f "NotInLookup" }}.end()) {
{{ err . "value must not be in list " $r.NotIn }}
}
{{- end }}
Expand Down
14 changes: 14 additions & 0 deletions templates/cc/msg.go
Expand Up @@ -36,6 +36,13 @@ const msgTpl = `
{{- end }}
};
{{ end }}{{ end }}
{{ if has .Rules.Items.GetEnum "In" }} {{ if .Rules.Items.GetEnum.In }}
const std::set<{{ inType .Field .Rules.Items.GetEnum.In }}> {{ lookup .Field "InLookup" }} = {
{{- range .Rules.Items.GetEnum.In }}
{{ inKey $f . }},
{{- end }}
};
{{ end }}{{ end }}
{{ end }}{{ end }}
{{ if has .Rules "Items"}}{{ if .Rules.Items }}
Expand All @@ -46,6 +53,13 @@ const msgTpl = `
{{- end }}
};
{{ end }}{{ end }}
{{ if has .Rules.Items.GetEnum "NotIn" }} {{ if .Rules.Items.GetEnum.NotIn }}
const std::set<{{ inType .Field .Rules.Items.GetEnum.NotIn }}> {{ lookup .Field "NotInLookup" }} = {
{{- range .Rules.Items.GetEnum.NotIn }}
{{ inKey $f . }},
{{- end }}
};
{{ end }}{{ end }}
{{ end }}{{ end }}
{{ if has .Rules "Pattern"}}{{ if .Rules.Pattern }}
Expand Down
14 changes: 14 additions & 0 deletions templates/goshared/msg.go
Expand Up @@ -130,6 +130,13 @@ var _ interface{
{{- end }}
}
{{ end }}{{ end }}
{{ if has .Rules.Items.GetEnum "In" }} {{ if .Rules.Items.GetEnum.In }}
var {{ lookup .Field "InLookup" }} = map[{{ inType .Field .Rules.Items.GetEnum.In }}]struct{}{
{{- range .Rules.Items.GetEnum.In }}
{{ inKey $f . }}: {},
{{- end }}
}
{{ end }}{{ end }}
{{ end }}{{ end }}
{{ if has .Rules "Items"}}{{ if .Rules.Items }}
Expand All @@ -140,6 +147,13 @@ var _ interface{
{{- end }}
}
{{ end }}{{ end }}
{{ if has .Rules.Items.GetEnum "NotIn" }} {{ if .Rules.Items.GetEnum.NotIn }}
var {{ lookup .Field "NotInLookup" }} = map[{{ inType .Field .Rules.Items.GetEnum.NotIn }}]struct{}{
{{- range .Rules.Items.GetEnum.NotIn }}
{{ inKey $f . }}: {},
{{- end }}
}
{{ end }}{{ end }}
{{ end }}{{ end }}
{{ if has .Rules "Keys"}}{{ if .Rules.Keys }}
Expand Down
6 changes: 6 additions & 0 deletions templates/goshared/register.go
Expand Up @@ -215,6 +215,12 @@ func (fns goSharedFuncs) inType(f pgs.Field, x interface{}) string {
default:
return pgsgo.TypeName(fmt.Sprintf("%T", x)).Element().String()
}
case pgs.EnumT:
if f.Type().IsRepeated() {
return f.Type().Element().Enum().Name().String()
} else {
return fns.Type(f).String()
}
default:
return fns.Type(f).String()
}
Expand Down
6 changes: 6 additions & 0 deletions tests/harness/cases/repeated.proto
Expand Up @@ -9,6 +9,10 @@ import "validate/validate.proto";
import "google/protobuf/duration.proto";

message Embed { int64 val = 1 [(validate.rules).int64.gt = 0]; }
enum AnEnum {
X = 0;
Y = 1;
}

message RepeatedNone { repeated int64 val = 1; }
message RepeatedEmbedNone { repeated Embed val = 1; }
Expand All @@ -23,5 +27,7 @@ message RepeatedItemPattern { repeated string val = 1 [(validate.rules).repeate
message RepeatedEmbedSkip { repeated Embed val = 1 [(validate.rules).repeated.items.message.skip = true]; }
message RepeatedItemIn { repeated string val = 1 [(validate.rules).repeated.items.string = {in: ["foo", "bar"]}]; }
message RepeatedItemNotIn { repeated string val = 1 [(validate.rules).repeated.items.string = {not_in: ["foo", "bar"]}]; }
message RepeatedEnumIn { repeated AnEnum val = 1 [(validate.rules).repeated.items.enum = {in: [0]}]; }
message RepeatedEnumNotIn { repeated AnEnum val = 1 [(validate.rules).repeated.items.enum = {not_in: [0]}]; }
message RepeatedMinAndItemLen { repeated string val = 1 [(validate.rules).repeated = { items { string { len: 3 } }, min_items: 1 }]; }
message RepeatedDuration { repeated google.protobuf.Duration val = 1 [(validate.rules).repeated = { items { duration { gte { nanos: 1000000}}}}]; }
5 changes: 5 additions & 0 deletions tests/harness/executor/cases.go
Expand Up @@ -1071,6 +1071,11 @@ var repeatedCases = []TestCase{
{"repeated - items - invalid (not_in)", &cases.RepeatedItemNotIn{Val: []string{"foo"}}, false},
{"repeated - items - valid (not_in)", &cases.RepeatedItemNotIn{Val: []string{"baz"}}, true},

{"repeated - items - invalid (enum in)", &cases.RepeatedEnumIn{Val: []cases.AnEnum{1}}, false},
{"repeated - items - valid (enum in)", &cases.RepeatedEnumIn{Val: []cases.AnEnum{0}}, true},
{"repeated - items - invalid (enum not_in)", &cases.RepeatedEnumNotIn{Val: []cases.AnEnum{0}}, false},
{"repeated - items - valid (enum not_in)", &cases.RepeatedEnumNotIn{Val: []cases.AnEnum{1}}, true},

{"repeated - embed skip - valid", &cases.RepeatedEmbedSkip{Val: []*cases.Embed{{Val: 1}}}, true},
{"repeated - embed skip - valid (invalid element)", &cases.RepeatedEmbedSkip{Val: []*cases.Embed{{Val: -1}}}, true},
{"repeated - min and items len - valid", &cases.RepeatedMinAndItemLen{Val: []string{"aaa", "bbb"}}, true},
Expand Down

0 comments on commit 88233f7

Please sign in to comment.