@@ -76,7 +76,7 @@ extend google.protobuf.FieldOptions {
7676// `Rule` represents a validation rule written in the Common Expression
7777// Language (CEL) syntax. Each Rule includes a unique identifier, an
7878// optional error message, and the CEL expression to evaluate. For more
79- // information on CEL , [see our documentation](https://github.com/bufbuild /protovalidate/blob/main/docs/cel.md ).
79+ // information, [see our documentation](https://buf.build/docs /protovalidate/schemas/custom-rules/ ).
8080//
8181// ```proto
8282// message Foo {
@@ -121,8 +121,8 @@ message MessageRules {
121121 optional bool disabled = 1 ;
122122
123123 // `cel` is a repeated field of type Rule. Each Rule specifies a validation rule to be applied to this message.
124- // These rules are written in Common Expression Language (CEL) syntax. For more information on
125- // CEL, [see our documentation](https://github.com/bufbuild /protovalidate/blob/main/docs/cel.md ).
124+ // These rules are written in Common Expression Language (CEL) syntax. For more information,
125+ // [see our documentation](https://buf.build/docs /protovalidate/schemas/custom-rules/ ).
126126 //
127127 //
128128 // ```proto
@@ -137,6 +137,46 @@ message MessageRules {
137137 // }
138138 // ```
139139 repeated Rule cel = 3 ;
140+
141+ // `oneof` is a repeated field of type MessageOneofRule that specifies a list of fields
142+ // of which at most one can be present. If `required` is also specified, then exactly one
143+ // of the specified fields _must_ be present.
144+ //
145+ // This will enforce oneof-like constraints with a few features not provided by
146+ // actual Protobuf oneof declarations:
147+ // 1. Repeated and map fields are allowed in this validation. In a Protobuf oneof,
148+ // only scalar fields are allowed.
149+ // 2. Fields with implicit presence are allowed. In a Protobuf oneof, all member
150+ // fields have explicit presence. This means that, for the purpose of determining
151+ // how many fields are set, explicitly setting such a field to its zero value is
152+ // effectively the same as not setting it at all.
153+ // 3. This will generate validation errors when unmarshalling, even from the binary
154+ // format. With a Protobuf oneof, if multiple fields are present in the serialized
155+ // form, earlier values are usually silently ignored when unmarshalling, with only
156+ // the last field being present when unmarshalling completes.
157+ //
158+ //
159+ // ```proto
160+ // message MyMessage {
161+ // // Only one of `field1` or `field2` _can_ be present in this message.
162+ // option (buf.validate.message).oneof = { fields: ["field1", "field2"] };
163+ // // Only one of `field3` or `field4` _must_ be present in this message.
164+ // option (buf.validate.message).oneof = { fields: ["field3", "field4"], required: true };
165+ // string field1 = 1;
166+ // bytes field2 = 2;
167+ // bool field3 = 3;
168+ // int32 field4 = 4;
169+ // }
170+ // ```
171+ repeated MessageOneofRule oneof = 4 ;
172+ }
173+
174+ message MessageOneofRule {
175+ // A list of field names to include in the oneof. All field names must be
176+ // defined in the message.
177+ repeated string fields = 1 ;
178+ // If true, one of the fields specified _must_ be set.
179+ optional bool required = 2 ;
140180}
141181
142182// The `OneofRules` message type enables you to manage rules for
@@ -166,8 +206,8 @@ message OneofRules {
166206// the field, the correct set should be used to ensure proper validations.
167207message FieldRules {
168208 // `cel` is a repeated field used to represent a textual expression
169- // in the Common Expression Language (CEL) syntax. For more information on
170- // CEL, [see our documentation](https://github.com/bufbuild /protovalidate/blob/main/docs/cel.md ).
209+ // in the Common Expression Language (CEL) syntax. For more information,
210+ // [see our documentation](https://buf.build/docs /protovalidate/schemas/custom-rules/ ).
171211 //
172212 // ```proto
173213 // message MyMessage {
@@ -184,7 +224,7 @@ message FieldRules {
184224 // described as "serialized in the wire format," which includes:
185225 //
186226 // - the following "nullable" fields must be explicitly set to be considered populated:
187- // - singular message fields (whose fields may be unpopulated / default values)
227+ // - singular message fields (whose fields may be unpopulated/ default values)
188228 // - member fields of a oneof (may be their default value)
189229 // - proto3 optional fields (may be their default value)
190230 // - proto2 scalar fields (both optional and required)
@@ -251,8 +291,8 @@ message FieldRules {
251291// multiple fields.
252292message PredefinedRules {
253293 // `cel` is a repeated field used to represent a textual expression
254- // in the Common Expression Language (CEL) syntax. For more information on
255- // CEL, [see our documentation](https://github.com/bufbuild /protovalidate/blob/main/docs/cel.md ).
294+ // in the Common Expression Language (CEL) syntax. For more information,
295+ // [see our documentation](https://buf.build/docs /protovalidate/schemas/predefined-rules/ ).
256296 //
257297 // ```proto
258298 // message MyMessage {
@@ -276,7 +316,7 @@ message PredefinedRules {
276316// Specifies how FieldRules.ignore behaves. See the documentation for
277317// FieldRules.required for definitions of "populated" and "nullable".
278318enum Ignore {
279- // Validation is only skipped if it's an unpopulated nullable fields .
319+ // Validation is only skipped if it's an unpopulated nullable field .
280320 //
281321 // ```proto
282322 // syntax="proto3";
@@ -3809,7 +3849,7 @@ message StringRules {
38093849 extensions 1000 to max;
38103850}
38113851
3812- // WellKnownRegex contain some well-known patterns.
3852+ // KnownRegex contains some well-known patterns.
38133853enum KnownRegex {
38143854 KNOWN_REGEX_UNSPECIFIED = 0 ;
38153855
@@ -4816,7 +4856,7 @@ message TimestampRules {
48164856}
48174857
48184858// `Violations` is a collection of `Violation` messages. This message type is returned by
4819- // protovalidate when a proto message fails to meet the requirements set by the `Rule` validation rules.
4859+ // Protovalidate when a proto message fails to meet the requirements set by the `Rule` validation rules.
48204860// Each individual violation is represented by a `Violation` message.
48214861message Violations {
48224862 // `violations` is a repeated field that contains all the `Violation` messages corresponding to the violations detected.
@@ -4828,11 +4868,42 @@ message Violations {
48284868// caused the violation, the specific rule that wasn't fulfilled, and a
48294869// human-readable error message.
48304870//
4871+ // For example, consider the following message:
4872+ //
4873+ // ```proto
4874+ // message User {
4875+ // int32 age = 1 [(buf.validate.field).cel = {
4876+ // id: "user.age",
4877+ // expression: "this < 18 ? 'User must be at least 18 years old' : ''",
4878+ // }];
4879+ // }
4880+ // ```
4881+ //
4882+ // It could produce the following violation:
4883+ //
48314884// ```json
48324885// {
4833- // "fieldPath": "bar",
4834- // "ruleId": "foo.bar",
4835- // "message": "bar must be greater than 0"
4886+ // "ruleId": "user.age",
4887+ // "message": "User must be at least 18 years old",
4888+ // "field": {
4889+ // "elements": [
4890+ // {
4891+ // "fieldNumber": 1,
4892+ // "fieldName": "age",
4893+ // "fieldType": "TYPE_INT32"
4894+ // }
4895+ // ]
4896+ // },
4897+ // "rule": {
4898+ // "elements": [
4899+ // {
4900+ // "fieldNumber": 23,
4901+ // "fieldName": "cel",
4902+ // "fieldType": "TYPE_MESSAGE",
4903+ // "index": "0"
4904+ // }
4905+ // ]
4906+ // }
48364907// }
48374908// ```
48384909message Violation {
@@ -4857,7 +4928,7 @@ message Violation {
48574928 // ```
48584929 optional FieldPath field = 5 ;
48594930
4860- // `rule` is a machine-readable path that points to the specific rule rule that failed validation.
4931+ // `rule` is a machine-readable path that points to the specific rule that failed validation.
48614932 // This will be a nested field starting from the FieldRules of the field that failed validation.
48624933 // For custom rules, this will provide the path of the rule, e.g. `cel[0]`.
48634934 //
0 commit comments