cel 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da576b6bec07758040135b557e1e135952bee1e4e6bb4bc19768233b817bbe8f
4
- data.tar.gz: bce3a0b0b7cd41113898fc7ebfaa1a5e3adcd94fc84b5791ef2bd9a6e33b4a60
3
+ metadata.gz: bcb8e069501a6c9cfdf6af67f83701111d67130d04a9208a05482d14ac1c519a
4
+ data.tar.gz: 0af115f5924dd63f926227fd916c2fe3f2b25bb6a68e682df1c9f5be36b1be6f
5
5
  SHA512:
6
- metadata.gz: 88ad2004603260595e7995be27fd3f77d0e0de8a0c90e16569ce67c3018608530b1d0e2455e6a8a65949254818bdc698d3be8fea2c45866589eb153ddb3a7d4d
7
- data.tar.gz: '028149b8a3f5b06c0ae5ebb02f3d09144ec42af89506971c3677f8671e8ccace55ee8b575fb1282f32a041872edee4e44f1fd9a8cb14e6889ba343794e60ae0e'
6
+ metadata.gz: d78064a96c11a026f1b6f16a3ebdfed6f3f528170975ab9c26b1e7438c7805419830418f32e7b6557bafeace936c35f1dc18f695a1294862780c2aff9e0bc335
7
+ data.tar.gz: 9897a6ed3a7708cefaf1b6bd24f86802b1c50709cbbb9bab1fd843e31e3dc1f1f049f4770afa0c34ed89c91b30442a95738b30eb52d91e64d99f1dbc880e0de9
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.0] - 2025-06-12
4
+
5
+ ### Features
6
+
7
+ * Integration with `google-protobuf` (optional dependency) by evaluating messages to protobuf stubs, and making them an integral part of the CEL type set. Some examples:
8
+ * auto-conversion of protobuf wrapper types.
9
+ * enums support
10
+
11
+ ### Improvements
12
+
13
+ * More correct parsing, checking and evaluation of CEL expressions, thanks to the issues identified by conformance tests.
14
+
15
+ ### Chore
16
+
17
+ * Incorporation of the oficial cel-spec conformance tests into the test suite, to ensure feature correctness.
18
+ * `bigdecimal` added as explicit dependency.
19
+
3
20
  ## [0.2.3] - 2023-09-19
4
21
 
5
22
  ### Bugfixes
data/README.md CHANGED
@@ -107,9 +107,23 @@ env2 = environment(foo: -> (a, b) { a + b})
107
107
  env2.evaluate("foo(2, 2)") #=> 4
108
108
  ```
109
109
 
110
+ ## Spec Coverage
111
+
112
+ `cel` is tested against the conformance suite from the [cel-spec repository](https://github.com/google/cel-spec/tree/master/conformance), and supports all features from the language except:
113
+
114
+ * math extensions
115
+ * string extensions
116
+ * bindings extensions
117
+ * block extensions
118
+ * encoders extensions
119
+ * comprehensions V2 API
120
+ * optionals
121
+
122
+ If this is something you're interested in (helping out), add a mention in the corresponding issue (or create one when non is available already).
123
+
110
124
  ## Supported Rubies
111
125
 
112
- All Rubies greater or equal to 2.5, and always latest JRuby and Truffleruby.
126
+ All Rubies greater or equal to 2.7, and always latest JRuby and Truffleruby.
113
127
 
114
128
  ## Development
115
129
 
@@ -118,8 +132,16 @@ Clone the repo in your local machine, where you have `ruby` installed. Then you
118
132
  ```bash
119
133
  # install dev dependencies
120
134
  > bundle install
135
+ # create protobuf stubs for tests
136
+ > git clone --depth 1 https://github.com/google/cel-spec.git
137
+ > git clone --depth 1 https://github.com/googleapis/googleapis.git
138
+ > bundle exec rake build_test_protos
121
139
  # run tests
122
140
  > bundle exec rake test
141
+ # build protobuf stubs for conformance tests
142
+ > bundle exec rake build_conformance_protos
143
+ # run conformance tests
144
+ > bundle exec rake conformance
123
145
  ```
124
146
 
125
147
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "google/protobuf/descriptor_pb"
3
4
  require "google/protobuf/struct_pb"
4
5
  require "google/protobuf/wrappers_pb"
5
6
  require "google/protobuf/any_pb"
@@ -9,94 +10,287 @@ module Cel
9
10
  module Protobuf
10
11
  module_function
11
12
 
12
- def convert_from_protobuf(msg)
13
+ def base_class
14
+ Google::Protobuf::MessageExts
15
+ end
16
+
17
+ def map_class
18
+ Google::Protobuf::Map
19
+ end
20
+
21
+ def timestamp_class
22
+ Google::Protobuf::Timestamp
23
+ end
24
+
25
+ def duration_class
26
+ Google::Protobuf::Duration
27
+ end
28
+
29
+ def enum_class
30
+ Enum
31
+ end
32
+
33
+ def try_convert_from_wrapper(msg)
13
34
  case msg
14
35
  when Google::Protobuf::Any
36
+ raise EvaluateError, "error conversion for empty Any" unless msg.type_name
15
37
 
16
- any.unpack(type_msg).to_ruby
38
+ type_msg = Object.const_get(Cel.package_to_module_name(msg.type_name))
39
+ try_convert_from_wrapper(msg.unpack(type_msg))
17
40
  when Google::Protobuf::ListValue
18
41
  msg.to_a
19
42
  when Google::Protobuf::Struct
20
43
  msg.to_h
21
44
  when Google::Protobuf::Value
22
- msg.to_ruby
45
+ msg.to_ruby(true)
46
+ when Google::Protobuf::BytesValue
47
+ Cel::Bytes.new(msg.value.bytes)
48
+ when Google::Protobuf::Int32Value,
49
+ Google::Protobuf::Int64Value
50
+ Cel::Number.new(:int, msg.value)
51
+ when Google::Protobuf::UInt32Value,
52
+ Google::Protobuf::UInt64Value
53
+ Cel::Number.new(:uint, msg.value)
54
+ when Google::Protobuf::DoubleValue,
55
+ Google::Protobuf::FloatValue
56
+ Cel::Number.new(:double, msg.value)
23
57
  when Google::Protobuf::BoolValue,
24
- Google::Protobuf::BytesValue,
25
- Google::Protobuf::DoubleValue,
26
- Google::Protobuf::FloatValue,
27
- Google::Protobuf::Int32Value,
28
- Google::Protobuf::Int64Value,
29
- Google::Protobuf::UInt32Value,
30
- Google::Protobuf::UInt64Value,
31
58
  Google::Protobuf::NullValue,
32
59
  Google::Protobuf::StringValue
60
+ # conversion to cel type won't be ambiguous here
33
61
  msg.value
34
62
  when Google::Protobuf::Timestamp
35
63
  msg.to_time
36
64
  when Google::Protobuf::Duration
37
65
  Cel::Duration.new(seconds: msg.seconds, nanos: msg.nanos)
38
66
  else
39
- raise Error, "#{msg.class}: protobuf to cel unsupported"
67
+ msg.extend(CelComparisonMode)
68
+ msg
69
+ end
70
+ end
71
+
72
+ def try_convert_from_wrapper_type(*)
73
+ TYPES[:map]
74
+ end
75
+
76
+ def convert_to_proto_type(type, package)
77
+ proto_type = Cel.package_to_module_name(type)
78
+
79
+ return unless proto_type
80
+
81
+ return Object.const_get(proto_type) if Object.const_defined?(proto_type)
82
+
83
+ return unless package
84
+
85
+ return unless package.const_defined?(proto_type)
86
+
87
+ package.const_get(proto_type)
88
+ end
89
+
90
+ def convert_to_cel_type(proto, package)
91
+ case proto
92
+ when Google::Protobuf::FieldDescriptor
93
+
94
+ cel_type =
95
+ case proto.type
96
+ when :int32, :int64, :sint32, :sint64, :sfixed32, :sfixed64, :enum
97
+ TYPES[:int]
98
+ when :uint32, :uint64, :fixed32, :fixed64
99
+ TYPES[:uint]
100
+ when :float, :double
101
+ TYPES[:double]
102
+ when :bool
103
+ TYPES[:bool]
104
+ when :string
105
+ TYPES[:string]
106
+ when :bytes
107
+ TYPES[:bytes]
108
+ when :message
109
+ proto_type = convert_to_proto_type(proto.submsg_name, package)
110
+
111
+ proto_type = PROTO_TO_CEL_TYPE[proto_type] if PROTO_TO_CEL_TYPE.key?(proto_type)
112
+ proto_type
113
+ end
114
+
115
+ if proto.label == :repeated
116
+ return TYPES[:list, cel_type] unless proto.subtype
117
+
118
+ case proto.subtype.options
119
+ when Google::Protobuf::EnumOptions
120
+ return TYPES[:list, cel_type]
121
+ when Google::Protobuf::MessageOptions
122
+ # protobuf doesn't have a way to identify whether this field descriptors is from a map,
123
+ # nor the types for key and values.
124
+ return TYPES[:map, cel_type] if proto.subtype.options.map_entry
125
+ end
126
+
127
+ return TYPES[:list, cel_type]
128
+ end
129
+
130
+ cel_type
131
+ else
132
+ PROTO_TO_CEL_TYPE[proto]
40
133
  end
41
134
  end
42
135
 
43
- def convert_from_type(type, value)
44
- case type
45
- when "Any", "google.protobuf.Any"
46
- type_url = value[Identifier.new("type_url")].value
47
- _, type_msg = type_url.split("/", 2)
48
- type_msg = const_get(type_msg.split(".").map(&:capitalize).join("::"))
49
- encoded_msg = value[Identifier.new("value")].value.pack("C*")
50
- any = Google::Protobuf::Any.new(type_url: type_url, value: encoded_msg)
51
- value = Literal.to_cel_type(any.unpack(type_msg).to_ruby)
52
- when "ListValue", "google.protobuf.ListValue"
53
- value = value.nil? ? List.new([]) : value[Identifier.new("values")]
54
- when "Struct", "google.protobuf.Struct"
55
- value = value.nil? ? Map.new({}) : value[Identifier.new("fields")]
56
- when "Value", "google.protobuf.Value"
57
- return Null.new if value.nil?
58
-
59
- key = value.keys.first
60
-
61
- value = value.fetch(key, value)
62
-
63
- value = case key
64
- when "null_value"
65
- Null.new if value.zero?
66
- when "number_value"
67
- value = -value.operands.first if value.is_a?(Operation) && value.op == "-" && value.unary?
68
- Number.new(:double, value)
69
- else
70
- value
136
+ def convert_to_proto(proto_type, values, convert_value_to_proto: false)
137
+ return values.unpack(proto_type) if values.is_a?(Google::Protobuf::Any)
138
+
139
+ if proto_type == Google::Protobuf::Struct
140
+ values = values[:fields] if values.key?(:fields)
141
+
142
+ raise EvaluateError, "bad key type" unless values.all? { |k, _| k.is_a?(::String) }
143
+
144
+ proto_type.from_hash(values)
145
+ elsif proto_type == Google::Protobuf::ListValue
146
+ if values.is_a?(Hash) && values.key?(:values)
147
+ proto_type.from_a(values[:values])
148
+ else
149
+ proto_type.from_a(values)
150
+ end
151
+ elsif proto_type == Google::Protobuf::NullValue
152
+ nil
153
+ elsif proto_type == Google::Protobuf::Value
154
+ case values
155
+ when Google::Protobuf::Duration
156
+ proto_type.new(string_value: "#{values.seconds}#{if values.nanos.positive?
157
+ ".#{values.nanos / 1_000_000_000.0}"
158
+ end}s")
159
+ when Google::Protobuf::Timestamp
160
+ proto_type.new(string_value: values.to_time.utc.iso8601(9))
161
+ when Hash
162
+ if values.key?(:struct_value)
163
+
164
+ raise EvaluateError, "bad key type" unless values[:struct_value].all? { |k, _| k.is_a?(::String) }
165
+
166
+ values[:struct_value] = Google::Protobuf::Struct.from_hash(values[:struct_value])
167
+ elsif values.key?(:list_value)
168
+ values[:list_value] = Google::Protobuf::ListValue.from_a(values[:list_value])
169
+ elsif values.empty?
170
+ if convert_value_to_proto
171
+ values = { struct_value: Google::Protobuf::Struct.from_hash(values) }
172
+ else
173
+ values[:null_value] = Google::Protobuf::NullValue::NULL_VALUE
174
+ end
175
+ elsif values.any? { |k, _| proto_type.descriptor.lookup(k.to_s).nil? }
176
+ raise EvaluateError, "bad key type" unless values.all? { |k, _| k.is_a?(::String) }
177
+
178
+ values = { struct_value: Google::Protobuf::Struct.from_hash(values) }
179
+ end
180
+ proto_type.new(values)
181
+ when Google::Protobuf::BoolValue
182
+ proto_type.new(bool_value: values.value)
183
+ when Google::Protobuf::DoubleValue,
184
+ Google::Protobuf::FloatValue,
185
+ Google::Protobuf::Int32Value,
186
+ Google::Protobuf::UInt32Value
187
+ proto_type.new(number_value: values.value)
188
+ when Google::Protobuf::Int64Value,
189
+ Google::Protobuf::UInt64Value
190
+ if values.value >= MAX_INT - 1
191
+ proto_type.new(string_value: values.value.to_s)
192
+ else
193
+ proto_type.new(number_value: values.value)
194
+ end
195
+ when Google::Protobuf::StringValue
196
+ proto_type.new(string_value: values.value)
197
+ when Google::Protobuf::BytesValue
198
+ proto_type.new(string_value: [values.value].pack("m0"))
199
+ when Google::Protobuf::NullValue
200
+ proto_type.new(null_value: Google::Protobuf::NullValue::NULL_VALUE)
201
+ when Google::Protobuf::Struct
202
+ proto_type.new(struct_value: values.value)
203
+ when Google::Protobuf::ListValue
204
+ proto_type.new(list_value: values.value)
205
+ when Google::Protobuf::Empty
206
+ proto_type.from_ruby({})
207
+ when Google::Protobuf::FieldMask
208
+ proto_type.from_ruby(values.paths.join(","))
209
+ else
210
+ proto_type.from_ruby(values)
211
+ end
212
+ elsif proto_type == Google::Protobuf::Any
213
+ case values
214
+ when Array
215
+ proto_type.pack(Google::Protobuf::ListValue.from_a(values))
216
+ when Hash
217
+ # type_url: "", value: ""
218
+ # TODO: consider pattern matching
219
+ if convert_value_to_proto
220
+ proto_type.pack(Google::Protobuf::Struct.from_hash(values))
221
+ else
222
+ proto_type.new(values)
223
+ end
224
+ when base_class
225
+ proto_type.pack(values)
226
+ else
227
+ proto_type.pack(Google::Protobuf::Value.from_ruby(values))
228
+ end
229
+ elsif proto_type == Google::Protobuf::Timestamp
230
+ case values
231
+ when Time
232
+ proto_type.from_time(values)
233
+ when nil
234
+ nil
235
+ else
236
+ proto_type.new(values)
237
+ end
238
+ elsif proto_type == Google::Protobuf::Duration
239
+ case values
240
+ when Numeric
241
+ seconds, nanos = values.divmod(1)
242
+ nanos *= 1_000_000_000
243
+ proto_type.new(seconds: seconds, nanos: nanos)
244
+ when nil
245
+ nil
246
+ else
247
+ proto_type.new(values)
248
+ end
249
+ elsif values.is_a?(Hash)
250
+ values = values.to_h do |key, value|
251
+ field_descriptor = proto_type.descriptor.lookup(key.to_s)
252
+ if value.nil? && (NILLABLE_WRAPPERS.include?(field_descriptor.subtype.msgclass) ||
253
+ proto_type.descriptor.enum_for(:each_oneof).one? do |oneof|
254
+ oneof.enum_for(:each).include?(field_descriptor)
255
+ end)
256
+
257
+ next([key, value])
258
+ end
259
+
260
+ next([key, value]) unless field_descriptor && field_descriptor.type != :enum
261
+
262
+ field_subtype = field_descriptor.subtype
263
+
264
+ next([key, value]) unless field_subtype
265
+
266
+ [
267
+ key,
268
+ # discard protobuf enums as well
269
+ value.is_a?(field_subtype.msgclass) ?
270
+ value :
271
+ convert_to_proto(field_subtype.msgclass, value, convert_value_to_proto: true),
272
+ ]
71
273
  end
72
- when "BoolValue", "google.protobuf.BoolValue"
73
- value = value.nil? ? Bool.new(false) : value[Identifier.new("value")]
74
- when "BytesValue", "google.protobuf.BytesValue"
75
- value = value[Identifier.new("value")]
76
- when "DoubleValue", "google.protobuf.DoubleValue",
77
- "FloatValue", "google.protobuf.FloatValue"
78
- value = value.nil? ? Number.new(:double, 0.0) : value[Identifier.new("value")]
79
- value.type = TYPES[:double]
80
- when "Int32Value", "google.protobuf.Int32Value",
81
- "Int64Value", "google.protobuf.Int64Value"
82
- value = value.nil? ? Number.new(:int, 0) : value[Identifier.new("value")]
83
- when "Uint32Value", "google.protobuf.UInt32Value",
84
- "Uint64Value", "google.protobuf.UInt64Value"
85
- value = value.nil? ? Number.new(:uint, 0) : value[Identifier.new("value")]
86
- when "NullValue", "google.protobuf.NullValue"
87
- value = Null.new
88
- when "StringValue", "google.protobuf.StringValue"
89
- value = value.nil? ? String.new(+"") : value[Identifier.new("value")]
90
- when "Timestamp", "google.protobuf.Timestamp"
91
- seconds = value.fetch(Identifier.new("seconds"), 0)
92
- nanos = value.fetch(Identifier.new("nanos"), 0)
93
- value = Timestamp.new(Time.at(seconds, nanos, :nanosecond))
94
- when "Duration", "google.protobuf.Duration"
95
- seconds = value.fetch(Identifier.new("seconds"), 0)
96
- nanos = value.fetch(Identifier.new("nanos"), 0)
97
- value = Duration.new(seconds: seconds, nanos: nanos)
274
+
275
+ # protobuf sets maps as abstract classes, and there's apparently no way to identify them
276
+ # regardless, since their type is "message". Checking for ruby class name is the best
277
+ # proxy I could come up with.
278
+ return values unless proto_type.name
279
+
280
+ proto_type.new(values)
281
+ elsif values.nil?
282
+ Google::Protobuf::Value.from_ruby(values)
283
+ else
284
+ proto_type.new(value: values)
285
+ end
286
+ end
287
+
288
+ def convert_to_enum(value, proto_type = nil)
289
+ if proto_type
290
+ Enum.new(value, proto_type)
291
+ else
292
+ Enum.new(value)
98
293
  end
99
- value
100
294
  end
101
295
 
102
296
  def try_invoke_from(var, func, args)
@@ -129,5 +323,156 @@ module Cel
129
323
  Literal.to_cel_type(value)
130
324
  end
131
325
  end
326
+
327
+ # finds value for +attribute+ declared in the +proto+.
328
+ #
329
+ # if none is found, and if +attribute+ is another proto message, then return an instance of the type.
330
+ # if field is an enum,
331
+ def lookup(proto, attribute)
332
+ value = proto.public_send(attribute)
333
+
334
+ field = proto.class.descriptor.lookup(attribute.to_s)
335
+
336
+ case field.label
337
+ when :repeated
338
+ case value
339
+ when Google::Protobuf::Map
340
+ value.to_h { |k, v| [k, convert_from_proto_field_type(field, v)] } # rubocop:disable Style/HashTransformValues
341
+ else
342
+ value.map { |v| convert_from_proto_field_type(field, v) }
343
+ end
344
+ else
345
+ convert_from_proto_field_type(field, value)
346
+ end
347
+ end
348
+
349
+ def convert_from_proto_field_type(field, value)
350
+ if value.nil? && (field.type == :message)
351
+ subtype = field.subtype.msgclass
352
+
353
+ if NILLABLE_WRAPPERS.include?(subtype) ||
354
+ subtype == Google::Protobuf::Value
355
+ # if a wrapper type, ignore null
356
+ else
357
+ value = subtype.new
358
+ end
359
+ end
360
+
361
+ case field.type
362
+ when :message
363
+ value
364
+ when :enum
365
+ enum_type = const_get(Cel.package_to_module_name(field.submsg_name))
366
+
367
+ return Enum.new(value, enum_type) if value.is_a?(Integer)
368
+
369
+ enum_mod = Cel.package_to_module_name(field.submsg_name)
370
+
371
+ Enum.new(const_get(enum_mod).resolve(value), enum_type)
372
+ when :int32, :int64, :sint32, :sint64, :sfixed32, :sfixed64
373
+ return unless value
374
+
375
+ Number.new(:int, value)
376
+ when :uint32, :uint64, :fixed32, :fixed64
377
+ return unless value
378
+
379
+ Number.new(:uint, value)
380
+ when :float, :double
381
+ return unless value
382
+
383
+ Number.new(:double, value)
384
+ when :bool
385
+ return unless value
386
+
387
+ Bool.cast(value)
388
+ when :string
389
+ return unless value
390
+
391
+ String.new(value)
392
+ when :bytes
393
+ return unless value
394
+
395
+ Bytes.new(value)
396
+ end
397
+ end
398
+
399
+ module CelComparisonMode
400
+ def ==(other)
401
+ super || begin
402
+ return false unless other.is_a?(Protobuf.base_class)
403
+
404
+ a1 = self
405
+ a2 = other
406
+
407
+ if a1.is_a?(Google::Protobuf::Any) && !a1.type_url.empty?
408
+ a1 = a1.unpack(Object.const_get(Cel.package_to_module_name(a1.type_name)))
409
+ a1.extend(CelComparisonMode)
410
+ end
411
+
412
+ if a2.is_a?(Google::Protobuf::Any) && !a2.type_url.empty?
413
+ a2 = a2.unpack(Object.const_get(Cel.package_to_module_name(a2.type_name)))
414
+ end
415
+
416
+ return false unless a1.class == a2.class
417
+
418
+ if a1.is_a?(Google::Protobuf::Any) && a1.type_url.empty?
419
+ a2.is_a?(Google::Protobuf::Any) && a2.type_url.empty?
420
+ return a1.value == a2.value
421
+ end
422
+
423
+ a1.class.descriptor.each do |field|
424
+ f1 = a1.public_send(field.name)
425
+ f1.extend(CelComparisonMode) if f1.is_a?(Protobuf.base_class)
426
+ f2 = a2.public_send(field.name)
427
+ return false unless f1 == f2
428
+ end
429
+ true
430
+ end
431
+ end
432
+ end
433
+
434
+ class Enum < Cel::Number
435
+ # protocol buffer enum fields can accept any signed 32-bit number, values outside that range will raise an error.
436
+ MAX_ENUM_INT = (2**31)
437
+
438
+ def initialize(value, enum_type = nil)
439
+ super(:int, value)
440
+ @enum_type = enum_type
441
+ check_overflow(@value)
442
+ end
443
+
444
+ def enum_type
445
+ @enum_type || type
446
+ end
447
+
448
+ private
449
+
450
+ def check_overflow(value)
451
+ raise EvaluateError, "return error for overflow" unless (-(MAX_ENUM_INT - 1)...MAX_ENUM_INT).cover?(value)
452
+ end
453
+ end
454
+
455
+ PROTO_TO_CEL_TYPE = {
456
+ Google::Protobuf::Any => TYPES[:any],
457
+ Google::Protobuf::Value => TYPES[:any],
458
+ Google::Protobuf::ListValue => TYPES[:list],
459
+ Google::Protobuf::Struct => TYPES[:map],
460
+ Google::Protobuf::BoolValue => TYPES[:bool],
461
+ Google::Protobuf::BytesValue => TYPES[:bytes],
462
+ Google::Protobuf::DoubleValue => TYPES[:double],
463
+ Google::Protobuf::FloatValue => TYPES[:double],
464
+ Google::Protobuf::Int32Value => TYPES[:int],
465
+ Google::Protobuf::Int64Value => TYPES[:int],
466
+ Google::Protobuf::UInt32Value => TYPES[:uint],
467
+ Google::Protobuf::UInt64Value => TYPES[:uint],
468
+ Google::Protobuf::NullValue => TYPES[:null],
469
+ Google::Protobuf::StringValue => TYPES[:string],
470
+ Google::Protobuf::Timestamp => TYPES[:timestamp],
471
+ Google::Protobuf::Duration => TYPES[:duration],
472
+ }.freeze
473
+
474
+ NILLABLE_WRAPPERS = (PROTO_TO_CEL_TYPE.keys - [Google::Protobuf::Value, Google::Protobuf::ListValue,
475
+ Google::Protobuf::Struct, Google::Protobuf::Duration,
476
+ Google::Protobuf::Timestamp]).freeze
132
477
  end
133
478
  end