Skip to content

Commit a5be185

Browse files
l46kokcopybara-github
authored andcommitted
Perform field selections on lite messages by reading from the wire format
PiperOrigin-RevId: 748423924
1 parent 2062875 commit a5be185

21 files changed

+1356
-43
lines changed

common/internal/BUILD.bazel

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ java_library(
1616
exports = ["//common/src/main/java/dev/cel/common/internal:comparison_functions"],
1717
)
1818

19+
java_library(
20+
name = "cel_lite_descriptor_pool",
21+
exports = ["//common/src/main/java/dev/cel/common/internal:cel_lite_descriptor_pool"],
22+
)
23+
24+
java_library(
25+
name = "default_lite_descriptor_pool",
26+
exports = ["//common/src/main/java/dev/cel/common/internal:default_lite_descriptor_pool"],
27+
)
28+
1929
cel_android_library(
2030
name = "comparison_functions_android",
2131
exports = ["//common/src/main/java/dev/cel/common/internal:comparison_functions_android"],

common/src/main/java/dev/cel/common/internal/BUILD.bazel

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,34 @@ java_library(
294294
],
295295
)
296296

297+
java_library(
298+
name = "cel_lite_descriptor_pool",
299+
srcs = ["CelLiteDescriptorPool.java"],
300+
tags = [
301+
],
302+
deps = [
303+
"//protobuf:cel_lite_descriptor",
304+
"@maven//:com_google_errorprone_error_prone_annotations",
305+
],
306+
)
307+
308+
java_library(
309+
name = "default_lite_descriptor_pool",
310+
srcs = ["DefaultLiteDescriptorPool.java"],
311+
tags = [
312+
],
313+
deps = [
314+
":cel_lite_descriptor_pool",
315+
"//common/annotations",
316+
"//common/internal:well_known_proto",
317+
"//protobuf:cel_lite_descriptor",
318+
"@maven//:com_google_errorprone_error_prone_annotations",
319+
"@maven//:com_google_guava_guava",
320+
"@maven//:com_google_protobuf_protobuf_java",
321+
"@maven_android//:com_google_protobuf_protobuf_javalite",
322+
],
323+
)
324+
297325
java_library(
298326
name = "safe_string_formatter",
299327
srcs = ["SafeStringFormatter.java"],
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package dev.cel.common.internal;
16+
17+
import com.google.errorprone.annotations.Immutable;
18+
import dev.cel.protobuf.CelLiteDescriptor.MessageLiteDescriptor;
19+
import java.util.Optional;
20+
21+
/**
22+
* CelLiteDescriptorPool allows lookup of {@link MessageLiteDescriptor} by its fully qualified name.
23+
*/
24+
@Immutable
25+
public interface CelLiteDescriptorPool {
26+
Optional<MessageLiteDescriptor> findDescriptor(String protoTypeName);
27+
28+
MessageLiteDescriptor getDescriptorOrThrow(String protoTypeName);
29+
}
Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package dev.cel.common.internal;
16+
17+
import com.google.common.collect.ImmutableList;
18+
import com.google.common.collect.ImmutableMap;
19+
import com.google.common.collect.ImmutableSet;
20+
import com.google.errorprone.annotations.Immutable;
21+
import com.google.protobuf.Any;
22+
import com.google.protobuf.BoolValue;
23+
import com.google.protobuf.BytesValue;
24+
import com.google.protobuf.DoubleValue;
25+
import com.google.protobuf.Duration;
26+
import com.google.protobuf.Empty;
27+
import com.google.protobuf.FieldMask;
28+
import com.google.protobuf.FloatValue;
29+
import com.google.protobuf.Int32Value;
30+
import com.google.protobuf.Int64Value;
31+
import com.google.protobuf.ListValue;
32+
import com.google.protobuf.MessageLite;
33+
import com.google.protobuf.StringValue;
34+
import com.google.protobuf.Struct;
35+
import com.google.protobuf.Timestamp;
36+
import com.google.protobuf.UInt32Value;
37+
import com.google.protobuf.UInt64Value;
38+
import com.google.protobuf.Value;
39+
import dev.cel.common.annotations.Internal;
40+
import dev.cel.protobuf.CelLiteDescriptor;
41+
import dev.cel.protobuf.CelLiteDescriptor.FieldLiteDescriptor;
42+
import dev.cel.protobuf.CelLiteDescriptor.FieldLiteDescriptor.CelFieldValueType;
43+
import dev.cel.protobuf.CelLiteDescriptor.MessageLiteDescriptor;
44+
import java.util.NoSuchElementException;
45+
import java.util.Optional;
46+
import java.util.function.Supplier;
47+
48+
/** Descriptor pool for {@link CelLiteDescriptor}s. */
49+
@Immutable
50+
@Internal
51+
public final class DefaultLiteDescriptorPool implements CelLiteDescriptorPool {
52+
private final ImmutableMap<String, MessageLiteDescriptor> protoFqnToMessageInfo;
53+
54+
public static DefaultLiteDescriptorPool newInstance(ImmutableSet<CelLiteDescriptor> descriptors) {
55+
return new DefaultLiteDescriptorPool(descriptors);
56+
}
57+
58+
@Override
59+
public Optional<MessageLiteDescriptor> findDescriptor(String protoTypeName) {
60+
return Optional.ofNullable(protoFqnToMessageInfo.get(protoTypeName));
61+
}
62+
63+
@Override
64+
public MessageLiteDescriptor getDescriptorOrThrow(String protoTypeName) {
65+
return findDescriptor(protoTypeName)
66+
.orElseThrow(
67+
() -> new NoSuchElementException("Could not find a descriptor for: " + protoTypeName));
68+
}
69+
70+
private static MessageLiteDescriptor newMessageInfo(WellKnownProto wellKnownProto) {
71+
ImmutableList.Builder<FieldLiteDescriptor> fieldDescriptors = ImmutableList.builder();
72+
Supplier<MessageLite.Builder> messageBuilder = null;
73+
switch (wellKnownProto) {
74+
case ANY_VALUE:
75+
messageBuilder = Any::newBuilder;
76+
fieldDescriptors
77+
.add(
78+
newPrimitiveFieldDescriptor(
79+
1,
80+
"type_url",
81+
FieldLiteDescriptor.JavaType.STRING,
82+
FieldLiteDescriptor.Type.STRING))
83+
.add(
84+
newPrimitiveFieldDescriptor(
85+
2,
86+
"value",
87+
FieldLiteDescriptor.JavaType.BYTE_STRING,
88+
FieldLiteDescriptor.Type.BYTES));
89+
break;
90+
case FIELD_MASK:
91+
messageBuilder = FieldMask::newBuilder;
92+
fieldDescriptors.add(
93+
new FieldLiteDescriptor(
94+
/* fieldNumber= */ 1,
95+
/* fieldName= */ "paths",
96+
/* javaType= */ FieldLiteDescriptor.JavaType.STRING,
97+
/* celFieldValueType= */ CelFieldValueType.LIST,
98+
/* protoFieldType= */ FieldLiteDescriptor.Type.STRING,
99+
/* isPacked= */ false,
100+
/* fieldProtoTypeName= */ ""));
101+
break;
102+
case BOOL_VALUE:
103+
messageBuilder = BoolValue::newBuilder;
104+
fieldDescriptors.add(
105+
newPrimitiveFieldDescriptor(
106+
1, "value", FieldLiteDescriptor.JavaType.BOOLEAN, FieldLiteDescriptor.Type.BOOL));
107+
break;
108+
case BYTES_VALUE:
109+
messageBuilder = BytesValue::newBuilder;
110+
fieldDescriptors.add(
111+
newPrimitiveFieldDescriptor(
112+
1,
113+
"value",
114+
FieldLiteDescriptor.JavaType.BYTE_STRING,
115+
FieldLiteDescriptor.Type.BYTES));
116+
break;
117+
case DOUBLE_VALUE:
118+
messageBuilder = DoubleValue::newBuilder;
119+
fieldDescriptors.add(
120+
newPrimitiveFieldDescriptor(
121+
1, "value", FieldLiteDescriptor.JavaType.DOUBLE, FieldLiteDescriptor.Type.DOUBLE));
122+
break;
123+
case FLOAT_VALUE:
124+
messageBuilder = FloatValue::newBuilder;
125+
fieldDescriptors.add(
126+
newPrimitiveFieldDescriptor(
127+
1, "value", FieldLiteDescriptor.JavaType.FLOAT, FieldLiteDescriptor.Type.FLOAT));
128+
break;
129+
case INT32_VALUE:
130+
messageBuilder = Int32Value::newBuilder;
131+
fieldDescriptors.add(
132+
newPrimitiveFieldDescriptor(
133+
1, "value", FieldLiteDescriptor.JavaType.INT, FieldLiteDescriptor.Type.INT32));
134+
break;
135+
case INT64_VALUE:
136+
messageBuilder = Int64Value::newBuilder;
137+
fieldDescriptors.add(
138+
newPrimitiveFieldDescriptor(
139+
1, "value", FieldLiteDescriptor.JavaType.LONG, FieldLiteDescriptor.Type.INT64));
140+
break;
141+
case STRING_VALUE:
142+
messageBuilder = StringValue::newBuilder;
143+
fieldDescriptors.add(
144+
newPrimitiveFieldDescriptor(
145+
1, "value", FieldLiteDescriptor.JavaType.STRING, FieldLiteDescriptor.Type.STRING));
146+
break;
147+
case UINT32_VALUE:
148+
messageBuilder = UInt32Value::newBuilder;
149+
fieldDescriptors.add(
150+
newPrimitiveFieldDescriptor(
151+
1, "value", FieldLiteDescriptor.JavaType.INT, FieldLiteDescriptor.Type.UINT32));
152+
break;
153+
case UINT64_VALUE:
154+
messageBuilder = UInt64Value::newBuilder;
155+
fieldDescriptors.add(
156+
newPrimitiveFieldDescriptor(
157+
1, "value", FieldLiteDescriptor.JavaType.LONG, FieldLiteDescriptor.Type.UINT64));
158+
break;
159+
case JSON_STRUCT_VALUE:
160+
messageBuilder = Struct::newBuilder;
161+
fieldDescriptors.add(
162+
new FieldLiteDescriptor(
163+
/* fieldNumber= */ 1,
164+
/* fieldName= */ "fields",
165+
/* javaType= */ FieldLiteDescriptor.JavaType.MESSAGE,
166+
/* celFieldValueType= */ CelFieldValueType.MAP,
167+
/* protoFieldType= */ FieldLiteDescriptor.Type.MESSAGE,
168+
/* isPacked= */ false,
169+
/* fieldProtoTypeName= */ "google.protobuf.Struct.FieldsEntry"));
170+
break;
171+
case JSON_VALUE:
172+
messageBuilder = Value::newBuilder;
173+
fieldDescriptors.add(
174+
new FieldLiteDescriptor(
175+
/* fieldNumber= */ 1,
176+
/* fieldName= */ "null_value",
177+
/* javaType= */ FieldLiteDescriptor.JavaType.ENUM,
178+
/* celFieldValueType= */ CelFieldValueType.SCALAR,
179+
/* protoFieldType= */ FieldLiteDescriptor.Type.ENUM,
180+
/* isPacked= */ false,
181+
/* fieldProtoTypeName= */ "google.protobuf.NullValue"));
182+
fieldDescriptors.add(
183+
new FieldLiteDescriptor(
184+
/* fieldNumber= */ 2,
185+
/* fieldName= */ "number_value",
186+
/* javaType= */ FieldLiteDescriptor.JavaType.DOUBLE,
187+
/* celFieldValueType= */ CelFieldValueType.SCALAR,
188+
/* protoFieldType= */ FieldLiteDescriptor.Type.DOUBLE,
189+
/* isPacked= */ false,
190+
/* fieldProtoTypeName= */ ""));
191+
fieldDescriptors.add(
192+
new FieldLiteDescriptor(
193+
/* fieldNumber= */ 3,
194+
/* fieldName= */ "string_value",
195+
/* javaType= */ FieldLiteDescriptor.JavaType.STRING,
196+
/* celFieldValueType= */ CelFieldValueType.SCALAR,
197+
/* protoFieldType= */ FieldLiteDescriptor.Type.STRING,
198+
/* isPacked= */ false,
199+
/* fieldProtoTypeName= */ ""));
200+
fieldDescriptors.add(
201+
new FieldLiteDescriptor(
202+
/* fieldNumber= */ 4,
203+
/* fieldName= */ "bool_value",
204+
/* javaType= */ FieldLiteDescriptor.JavaType.BOOLEAN,
205+
/* celFieldValueType= */ CelFieldValueType.SCALAR,
206+
/* protoFieldType= */ FieldLiteDescriptor.Type.BOOL,
207+
/* isPacked= */ false,
208+
/* fieldProtoTypeName= */ ""));
209+
fieldDescriptors.add(
210+
new FieldLiteDescriptor(
211+
/* fieldNumber= */ 5,
212+
/* fieldName= */ "struct_value",
213+
/* javaType= */ FieldLiteDescriptor.JavaType.MESSAGE,
214+
/* celFieldValueType= */ CelFieldValueType.SCALAR,
215+
/* protoFieldType= */ FieldLiteDescriptor.Type.MESSAGE,
216+
/* isPacked= */ false,
217+
/* fieldProtoTypeName= */ "google.protobuf.Struct"));
218+
fieldDescriptors.add(
219+
new FieldLiteDescriptor(
220+
/* fieldNumber= */ 6,
221+
/* fieldName= */ "list_value",
222+
/* javaType= */ FieldLiteDescriptor.JavaType.MESSAGE,
223+
/* celFieldValueType= */ CelFieldValueType.SCALAR,
224+
/* protoFieldType= */ FieldLiteDescriptor.Type.MESSAGE,
225+
/* isPacked= */ false,
226+
/* fieldProtoTypeName= */ "google.protobuf.ListValue"));
227+
break;
228+
case JSON_LIST_VALUE:
229+
messageBuilder = ListValue::newBuilder;
230+
fieldDescriptors.add(
231+
new FieldLiteDescriptor(
232+
/* fieldNumber= */ 1,
233+
/* fieldName= */ "values",
234+
/* javaType= */ FieldLiteDescriptor.JavaType.MESSAGE,
235+
/* celFieldValueType= */ CelFieldValueType.LIST,
236+
/* protoFieldType= */ FieldLiteDescriptor.Type.MESSAGE,
237+
/* isPacked= */ false,
238+
/* fieldProtoTypeName= */ "google.protobuf.Value"));
239+
break;
240+
case DURATION:
241+
messageBuilder = Duration::newBuilder;
242+
fieldDescriptors
243+
.add(
244+
newPrimitiveFieldDescriptor(
245+
1,
246+
"seconds",
247+
FieldLiteDescriptor.JavaType.LONG,
248+
FieldLiteDescriptor.Type.INT64))
249+
.add(
250+
newPrimitiveFieldDescriptor(
251+
2, "nanos", FieldLiteDescriptor.JavaType.INT, FieldLiteDescriptor.Type.INT32));
252+
break;
253+
case TIMESTAMP:
254+
messageBuilder = Timestamp::newBuilder;
255+
fieldDescriptors
256+
.add(
257+
newPrimitiveFieldDescriptor(
258+
1,
259+
"seconds",
260+
FieldLiteDescriptor.JavaType.LONG,
261+
FieldLiteDescriptor.Type.INT64))
262+
.add(
263+
newPrimitiveFieldDescriptor(
264+
2, "nanos", FieldLiteDescriptor.JavaType.INT, FieldLiteDescriptor.Type.INT32));
265+
break;
266+
case EMPTY:
267+
messageBuilder = Empty::newBuilder;
268+
}
269+
270+
return new MessageLiteDescriptor(
271+
wellKnownProto.typeName(), fieldDescriptors.build(), messageBuilder);
272+
}
273+
274+
private static FieldLiteDescriptor newPrimitiveFieldDescriptor(
275+
int fieldNumber,
276+
String fieldName,
277+
FieldLiteDescriptor.JavaType javaType,
278+
FieldLiteDescriptor.Type protoFieldType) {
279+
return new FieldLiteDescriptor(
280+
/* fieldNumber= */ fieldNumber,
281+
/* fieldName= */ fieldName,
282+
/* javaType= */ javaType,
283+
/* celFieldValueType= */ CelFieldValueType.SCALAR,
284+
/* protoFieldType= */ protoFieldType,
285+
/* isPacked= */ false,
286+
/* fieldProtoTypeName= */ "");
287+
}
288+
289+
private DefaultLiteDescriptorPool(ImmutableSet<CelLiteDescriptor> descriptors) {
290+
ImmutableMap.Builder<String, MessageLiteDescriptor> protoFqnMapBuilder = ImmutableMap.builder();
291+
for (WellKnownProto wellKnownProto : WellKnownProto.values()) {
292+
MessageLiteDescriptor wktMessageInfo = newMessageInfo(wellKnownProto);
293+
protoFqnMapBuilder.put(wellKnownProto.typeName(), wktMessageInfo);
294+
}
295+
296+
for (CelLiteDescriptor descriptor : descriptors) {
297+
protoFqnMapBuilder.putAll(descriptor.getProtoTypeNamesToDescriptors());
298+
}
299+
300+
this.protoFqnToMessageInfo = protoFqnMapBuilder.buildOrThrow();
301+
}
302+
}

0 commit comments

Comments
 (0)