Skip to content

Commit

Permalink
Conformance tests for enums and no wrapper. (google#157)
Browse files Browse the repository at this point in the history
Remove note about google.protobuf.EnumValue as a wrapper type.

Differentiates legacy and strong enum behavior. Implementations should disable one section or the other. Eventually the legacy behavior will be removed or wrapped with int conversions.
  • Loading branch information
JimLarson authored Nov 11, 2020
1 parent b2f5894 commit a47b2a1
Show file tree
Hide file tree
Showing 2 changed files with 1,138 additions and 18 deletions.
82 changes: 65 additions & 17 deletions doc/langdef.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,11 @@ combination of one or more of:
indicate that we're accessing a field within a protocol buffer or map.
* Protocol buffer package names: a simple or qualified name could represent an
absolute or relative name in the protocol buffer package namespace. Package
names must be followed by a message type or enum constant.
* Protocol buffer message types and enum constants: following an optional
protocol buffer package name, a simple or qualified name could refer to a
message type or enum constant in the package's namespace.
names must be followed by a message type, enum type, or enum constant.
* Protocol buffer message types, enum types, and enum constants: following an
optional protocol buffer package name, a simple or qualified name could
refer to a message type, and enum type, or an enum constant in the
package's namespace.

Resolution works as follows. If `a.b` is a name to be resolved in the context of
a protobuf declaration with scope `A.B`, then resolution is attempted, in order,
Expand Down Expand Up @@ -218,6 +219,16 @@ such as expression evaluation, rounding mode, or exception handling. However,
any two not-a-number values will compare equal even if their underlying
properties are different.

### Enumerations

Each protocol buffer enumeration is its own CEL type. Enumerations have no
operations other than equality (and inequality), obtaining the type from a
value, and conversion to an `int`. (No conversion to string is supported, as
an enum value might have 0, 1, or many names.) Values of type `int` can be
converted to enum values as long as they are in the range `-2^31` to `2^31 - 1`.
A value of type `string` can be converted to enum values as long as it is a
defined for that enum.

### String and Bytes Values

Strings are sequences of Unicode code points. Bytes are sequences of octets
Expand Down Expand Up @@ -392,11 +403,11 @@ int32, int64, sint32, sint64, sfixed32, sfixed64 | `int`
uint32, uint64, fixed32, fixed64 | `uint`
float, double | `double`
bool, string, bytes | same
enum | `int`
enum E | E
repeated | `list`
map<K, V> | `map`
oneof | options expanded individually, at most one is set
message | same except for conversions below
message M | M, except for conversions below

Signed integers, unsigned integers, and floating point numbers are converted to
the singular CEL type of the same sort. The CEL type is capable of expressing
Expand All @@ -406,10 +417,6 @@ buffers, an out-of-range CEL value results in an error.
Boolean, string, and bytes types have identical ranges and are converted without
error.

Protocol buffer enum values are converted to the corresponding `int` value.
Protocol buffer enum fields can accept any signed 32-bit number, values outside
that range will raise an error.

Repeated fields are converted to CEL lists of converted values, preserving the
order. In the other direction, the CEL list elements must be of the right type
and value to be converted to the corresponding protocol buffer type. Similarly,
Expand Down Expand Up @@ -449,12 +456,12 @@ google.protobuf message | CEL Conversion
`Value` | dynamically converted to the contained type (null, double, string, bool, `Struct`, or `ListValue`)
wrapper types | converted as eponymous field type

The wrapper types are `BoolValue`, `BytesValue`, `DoubleValue`, `EnumValue`,
`FloatValue`, `Int32Value`, `Int64Value`, `NullValue`, `StringValue`,
`Uint32Value`, and `Uint64Value`. Values of these wrapper types are converted to
the obvious type. Additionally, field selection of an unset message field of
wrapper type will evaluate to `null`, instead of the default message. This is an
exception to the usual evaluation of unset message fields.
The wrapper types are `BoolValue`, `BytesValue`, `DoubleValue`, `FloatValue`,
`Int32Value`, `Int64Value`, `NullValue`, `StringValue`, `Uint32Value`, and
`Uint64Value`. Values of these wrapper types are converted to the obvious type.
Additionally, field selection of an unset message field of wrapper type will
evaluate to `null`, instead of the default message. This is an exception to the
usual evaluation of unset message fields.

Note that this implies some cascading conversions. An `Any` message might be
converted to a `Struct`, one of whose `Value`-typed values might be converted to
Expand Down Expand Up @@ -1832,7 +1839,7 @@ See [cel-go/issues/9](https://github.com/google/cel-go/issues/9).
</td>
</tr>
<tr>
<th rowspan="5">
<th rowspan="6">
int
</th>
<td>
Expand Down Expand Up @@ -1866,6 +1873,14 @@ See [cel-go/issues/9](https://github.com/google/cel-go/issues/9).
type conversion
</td>
</tr>
<tr>
<td>
(enum E) -> int
</td>
<td>
type conversion
</td>
</tr>
<tr>
<td>
(google.protobuf.Timestamp) -> int
Expand Down Expand Up @@ -2080,6 +2095,39 @@ See [cel-go/issues/9](https://github.com/google/cel-go/issues/9).
type conversion
</td>
</tr>
<tr>
<th rowspan="2">
E (for fully-qualified enumeration E)
</th>
<td>
(int) -> enum E
</td>
<td>
type conversion when in int32 range, otherwise error
</td>
</tr>
<tr>
<td>
(string) -> enum E
</td>
<td>
type conversion for unqualified symbolic name, otherwise error
</td>
</tr>
</table>

<!-- END GENERATED DECL TABLE; DO NOT EDIT ABOVE -->

## Appendix 1: Legacy Behavior

### Enums

In many pre-1.0 implementations, protocol buffer enums are all treated as CEL
type `int`, and are legal arguments whenever an `int` is expected. Int values
in the range `-2**31` to `2**31 - 1` can be used whenever an enum is expected.
Values outside that range will raise an error. There are no standard functions
for conversion from strings, and no conversion to `int` is needed.

```
type(google.protobuf.Field{}.kind) # was int, now google.protobuf.Field.Kind
```
Loading

0 comments on commit a47b2a1

Please sign in to comment.