Skip to content

Commit cb38087

Browse files
l46kokcopybara-github
authored andcommitted
Fix double qualification in NamespacedAttribute
PiperOrigin-RevId: 912629467
1 parent 14d4c2e commit cb38087

17 files changed

Lines changed: 2664 additions & 46 deletions

File tree

common/internal/BUILD.bazel

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,8 @@ cel_android_library(
147147
name = "date_time_helpers_android",
148148
exports = ["//common/src/main/java/dev/cel/common/internal:date_time_helpers_android"],
149149
)
150+
151+
java_library(
152+
name = "reflection_util",
153+
exports = ["//common/src/main/java/dev/cel/common/internal:reflection_util"],
154+
)

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,8 +398,11 @@ java_library(
398398
java_library(
399399
name = "reflection_util",
400400
srcs = ["ReflectionUtil.java"],
401+
tags = [
402+
],
401403
deps = [
402404
"//common/annotations",
405+
"@maven//:com_google_guava_guava",
403406
],
404407
)
405408

common/src/main/java/dev/cel/common/internal/ReflectionUtil.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414

1515
package dev.cel.common.internal;
1616

17+
import com.google.common.reflect.TypeToken;
1718
import dev.cel.common.annotations.Internal;
1819
import java.lang.reflect.InvocationTargetException;
1920
import java.lang.reflect.Method;
21+
import java.lang.reflect.Type;
2022

2123
/**
2224
* Utility class for invoking Java reflection.
@@ -48,5 +50,20 @@ public static Object invoke(Method method, Object object, Object... params) {
4850
}
4951
}
5052

53+
/**
54+
* Resolves a generic parameter of a base class from a type token.
55+
*/
56+
public static Type resolveGenericParameter(TypeToken<?> token, Class<?> baseClass, int index) {
57+
return token.resolveType(baseClass.getTypeParameters()[index]).getType();
58+
}
59+
60+
/**
61+
* Extracts the raw Class from a Type. Handles Class, ParameterizedType, and WildcardType (returns
62+
* upper bound). Returns Object.class as fallback.
63+
*/
64+
public static Class<?> getRawType(Type type) {
65+
return TypeToken.of(type).getRawType();
66+
}
67+
5168
private ReflectionUtil() {}
5269
}

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

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ java_library(
6060
deps = [
6161
"//common/values",
6262
"@maven//:com_google_errorprone_error_prone_annotations",
63-
"@maven//:com_google_guava_guava",
6463
],
6564
)
6665

@@ -72,7 +71,6 @@ cel_android_library(
7271
deps = [
7372
"//common/values:values_android",
7473
"@maven//:com_google_errorprone_error_prone_annotations",
75-
"@maven_android//:com_google_guava_guava",
7674
],
7775
)
7876

@@ -118,7 +116,6 @@ java_library(
118116
deps = [
119117
":values",
120118
"//common/annotations",
121-
"@maven//:com_google_errorprone_error_prone_annotations",
122119
"@maven//:com_google_guava_guava",
123120
"@maven//:org_jspecify_jspecify",
124121
],
@@ -134,12 +131,31 @@ cel_android_library(
134131
deps = [
135132
":values_android",
136133
"//common/annotations",
137-
"@maven//:com_google_errorprone_error_prone_annotations",
138134
"@maven//:org_jspecify_jspecify",
139135
"@maven_android//:com_google_guava_guava",
140136
],
141137
)
142138

139+
java_library(
140+
name = "preadapted_list",
141+
srcs = [
142+
"CelPreAdaptedList.java",
143+
],
144+
tags = [
145+
],
146+
deps = ["//common/annotations"],
147+
)
148+
149+
cel_android_library(
150+
name = "preadapted_list_android",
151+
srcs = [
152+
"CelPreAdaptedList.java",
153+
],
154+
tags = [
155+
],
156+
deps = ["//common/annotations"],
157+
)
158+
143159
java_library(
144160
name = "values",
145161
srcs = CEL_VALUES_SOURCES,
@@ -148,6 +164,7 @@ java_library(
148164
deps = [
149165
":cel_byte_string",
150166
":cel_value",
167+
":preadapted_list",
151168
"//:auto_value",
152169
"//common/annotations",
153170
"//common/types",
@@ -198,6 +215,7 @@ cel_android_library(
198215
deps = [
199216
":cel_byte_string",
200217
":cel_value_android",
218+
":preadapted_list_android",
201219
"//:auto_value",
202220
"//common/annotations",
203221
"//common/types:type_providers_android",
@@ -226,7 +244,6 @@ java_library(
226244
],
227245
deps = [
228246
":cel_byte_string",
229-
":values",
230247
"//common/annotations",
231248
"//common/internal:proto_time_utils",
232249
"//common/internal:well_known_proto",
@@ -261,6 +278,7 @@ java_library(
261278
],
262279
deps = [
263280
":base_proto_cel_value_converter",
281+
":preadapted_list",
264282
":values",
265283
"//:auto_value",
266284
"//common:options",
@@ -273,7 +291,6 @@ java_library(
273291
"@maven//:com_google_errorprone_error_prone_annotations",
274292
"@maven//:com_google_guava_guava",
275293
"@maven//:com_google_protobuf_protobuf_java",
276-
"@maven//:org_jspecify_jspecify",
277294
],
278295
)
279296

@@ -316,8 +333,6 @@ java_library(
316333
"//protobuf:cel_lite_descriptor",
317334
"@maven//:com_google_errorprone_error_prone_annotations",
318335
"@maven//:com_google_guava_guava",
319-
"@maven//:com_google_protobuf_protobuf_java",
320-
"@maven//:org_jspecify_jspecify",
321336
"@maven_android//:com_google_protobuf_protobuf_javalite",
322337
],
323338
)
@@ -343,7 +358,6 @@ cel_android_library(
343358
"//protobuf:cel_lite_descriptor",
344359
"@maven//:com_google_errorprone_error_prone_annotations",
345360
"@maven//:com_google_guava_guava",
346-
"@maven//:org_jspecify_jspecify",
347361
"@maven_android//:com_google_guava_guava",
348362
"@maven_android//:com_google_protobuf_protobuf_javalite",
349363
],
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2026 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.values;
16+
17+
import dev.cel.common.annotations.Internal;
18+
import java.util.AbstractList;
19+
import java.util.List;
20+
import java.util.RandomAccess;
21+
22+
/**
23+
* A zero-allocation view over a list we know is already adapted.
24+
*
25+
* <p>This class purely exists as an optimization scheme to avoid redundant collection traversals in
26+
* {@link CelValueConverter}, and is not intended for general use.
27+
*/
28+
@Internal
29+
final class CelPreAdaptedList<E> extends AbstractList<E> implements RandomAccess {
30+
private final List<E> delegate;
31+
32+
private CelPreAdaptedList(List<E> delegate) {
33+
this.delegate = delegate;
34+
}
35+
36+
static <E> CelPreAdaptedList<E> wrap(List<E> safeList) {
37+
return new CelPreAdaptedList<>(safeList);
38+
}
39+
40+
@Override
41+
public E get(int index) {
42+
return delegate.get(index);
43+
}
44+
45+
@Override
46+
public int size() {
47+
return delegate.size();
48+
}
49+
}

common/src/main/java/dev/cel/common/values/CelValueConverter.java

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@
2020
import com.google.errorprone.annotations.Immutable;
2121
import dev.cel.common.annotations.Internal;
2222
import java.util.Collection;
23+
import java.util.Iterator;
24+
import java.util.List;
2325
import java.util.Map;
2426
import java.util.Optional;
27+
import java.util.RandomAccess;
2528
import java.util.function.Function;
2629

2730
/**
@@ -53,23 +56,46 @@ public static CelValueConverter getDefaultInstance() {
5356
* <p>The value may be a {@link CelValue}, a {@link Collection} or a {@link Map}.
5457
*/
5558
public Object maybeUnwrap(Object value) {
56-
if (value instanceof CelValue) {
57-
return unwrap((CelValue) value);
59+
if (value instanceof CelValue || value instanceof CelPreAdaptedList) {
60+
return value instanceof CelValue ? unwrap((CelValue) value) : value;
5861
}
5962

60-
Object mapped = mapContainer(value, maybeUnwrapFunction);
61-
if (mapped != value) {
62-
return mapped;
63-
}
64-
65-
return value;
63+
return mapContainer(value, maybeUnwrapFunction);
6664
}
6765

6866
/**
6967
* Maps a container (Collection or Map) by applying the provided mapper function to its elements.
7068
* Returns the original value if it's not a supported container.
7169
*/
7270
protected Object mapContainer(Object value, Function<Object, Object> mapper) {
71+
72+
// Zero allocation path for standard lists that support O(1) indexing
73+
// Generally, protobuf lists (backed by arrays) fall into this category
74+
if (value instanceof List && value instanceof RandomAccess) {
75+
List<Object> list = (List<Object>) value;
76+
for (int i = 0; i < list.size(); i++) {
77+
Object element = list.get(i);
78+
Object mapped = mapper.apply(element);
79+
80+
if (mapped != element) {
81+
ImmutableList.Builder<Object> builder =
82+
ImmutableList.builderWithExpectedSize(list.size());
83+
for (int j = 0; j < i; j++) {
84+
builder.add(list.get(j));
85+
}
86+
builder.add(mapped);
87+
for (int j = i + 1; j < list.size(); j++) {
88+
builder.add(mapper.apply(list.get(j)));
89+
}
90+
return builder.build();
91+
}
92+
}
93+
94+
// Zero allocations if unmodified
95+
return value;
96+
}
97+
98+
// Fallback for lists that are unordered
7399
if (value instanceof Collection) {
74100
Collection<Object> collection = (Collection<Object>) value;
75101
ImmutableList.Builder<Object> builder =
@@ -82,12 +108,32 @@ protected Object mapContainer(Object value, Function<Object, Object> mapper) {
82108

83109
if (value instanceof Map) {
84110
Map<Object, Object> map = (Map<Object, Object>) value;
85-
ImmutableMap.Builder<Object, Object> builder =
86-
ImmutableMap.builderWithExpectedSize(map.size());
87-
for (Map.Entry<Object, Object> entry : map.entrySet()) {
88-
builder.put(mapper.apply(entry.getKey()), mapper.apply(entry.getValue()));
111+
Iterator<Map.Entry<Object, Object>> iterator = map.entrySet().iterator();
112+
113+
while (iterator.hasNext()) {
114+
Map.Entry<Object, Object> entry = iterator.next();
115+
Object mappedKey = mapper.apply(entry.getKey());
116+
Object mappedValue = mapper.apply(entry.getValue());
117+
118+
if (mappedKey != entry.getKey() || mappedValue != entry.getValue()) {
119+
ImmutableMap.Builder<Object, Object> builder =
120+
ImmutableMap.builderWithExpectedSize(map.size());
121+
122+
for (Map.Entry<Object, Object> prevEntry : map.entrySet()) {
123+
if (prevEntry.getKey() == entry.getKey()) {
124+
break;
125+
}
126+
builder.put(mapper.apply(prevEntry.getKey()), mapper.apply(prevEntry.getValue()));
127+
}
128+
builder.put(mappedKey, mappedValue);
129+
while (iterator.hasNext()) {
130+
Map.Entry<Object, Object> nextEntry = iterator.next();
131+
builder.put(mapper.apply(nextEntry.getKey()), mapper.apply(nextEntry.getValue()));
132+
}
133+
return builder.buildOrThrow();
134+
}
89135
}
90-
return builder.buildOrThrow();
136+
return value;
91137
}
92138

93139
return value;
@@ -96,7 +142,7 @@ protected Object mapContainer(Object value, Function<Object, Object> mapper) {
96142
public Object toRuntimeValue(Object value) {
97143
Preconditions.checkNotNull(value);
98144

99-
if (value instanceof CelValue) {
145+
if (value instanceof CelValue || value instanceof CelPreAdaptedList) {
100146
return value;
101147
}
102148

common/src/main/java/dev/cel/common/values/ProtoCelValueConverter.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,18 @@ public Object fromProtoMessageFieldToCelValue(Message message, FieldDescriptor f
167167
break;
168168
}
169169

170+
if (fieldDescriptor.isRepeated()) {
171+
switch (fieldDescriptor.getType()) {
172+
case INT64:
173+
case BOOL:
174+
case STRING:
175+
case DOUBLE:
176+
return CelPreAdaptedList.wrap((List<?>) result);
177+
default:
178+
break;
179+
}
180+
}
181+
170182
return toRuntimeValue(result);
171183
}
172184

extensions/BUILD.bazel

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,8 @@ java_library(
5656
name = "comprehensions",
5757
exports = ["//extensions/src/main/java/dev/cel/extensions:comprehensions"],
5858
)
59+
60+
java_library(
61+
name = "native",
62+
exports = ["//extensions/src/main/java/dev/cel/extensions:native"],
63+
)

0 commit comments

Comments
 (0)