Skip to content

Commit dc8d775

Browse files
author
jchadwick-buf
authored
Implement getField CEL function (#271)
I'm proposing this as an eventual replacement (before 1.0) of our hack around the fact that the `in` identifier is reserved in CEL. We need this for protovalidate-cc especially so we can start removing our cel-cpp patches. Protovalidate PR: bufbuild/protovalidate#352
1 parent 8533e9e commit dc8d775

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

src/main/java/build/buf/protovalidate/CustomDeclarations.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ static List<Decl> create() {
3838
// Add 'now' variable declaration
3939
decls.add(Decls.newVar("now", Decls.newObjectType(TimestampT.TimestampType.typeName())));
4040

41+
// Add 'getField' function declaration
42+
decls.add(
43+
Decls.newFunction(
44+
"getField",
45+
Decls.newOverload(
46+
"get_field_any_string", Arrays.asList(Decls.Any, Decls.String), Decls.Any)));
47+
4148
// Add 'isIp' function declaration
4249
decls.add(
4350
Decls.newFunction(

src/main/java/build/buf/protovalidate/CustomOverload.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
package build.buf.protovalidate;
1616

17+
import com.google.protobuf.Descriptors;
18+
import com.google.protobuf.Message;
1719
import java.util.HashSet;
1820
import java.util.Set;
1921
import java.util.regex.Pattern;
@@ -23,6 +25,7 @@
2325
import org.projectnessie.cel.common.types.ListT;
2426
import org.projectnessie.cel.common.types.StringT;
2527
import org.projectnessie.cel.common.types.Types;
28+
import org.projectnessie.cel.common.types.pb.DefaultTypeAdapter;
2629
import org.projectnessie.cel.common.types.ref.TypeEnum;
2730
import org.projectnessie.cel.common.types.ref.Val;
2831
import org.projectnessie.cel.common.types.traits.Lister;
@@ -31,6 +34,7 @@
3134
/** Defines custom function overloads (the implementation). */
3235
final class CustomOverload {
3336

37+
private static final String OVERLOAD_GET_FIELD = "getField";
3438
private static final String OVERLOAD_FORMAT = "format";
3539
private static final String OVERLOAD_UNIQUE = "unique";
3640
private static final String OVERLOAD_STARTS_WITH = "startsWith";
@@ -58,6 +62,7 @@ final class CustomOverload {
5862
*/
5963
static Overload[] create() {
6064
return new Overload[] {
65+
celGetField(),
6166
celFormat(),
6267
celUnique(),
6368
celStartsWith(),
@@ -75,6 +80,30 @@ static Overload[] create() {
7580
};
7681
}
7782

83+
/**
84+
* Creates a custom function overload for the "getField" operation.
85+
*
86+
* @return The {@link Overload} instance for the "getField" operation.
87+
*/
88+
private static Overload celGetField() {
89+
return Overload.binary(
90+
OVERLOAD_GET_FIELD,
91+
(msgarg, namearg) -> {
92+
if (msgarg.type().typeEnum() != TypeEnum.Object
93+
|| namearg.type().typeEnum() != TypeEnum.String) {
94+
return Err.newErr("no such overload");
95+
}
96+
Message message = msgarg.convertToNative(Message.class);
97+
String fieldName = namearg.convertToNative(String.class);
98+
Descriptors.FieldDescriptor field =
99+
message.getDescriptorForType().findFieldByName(fieldName);
100+
if (field == null) {
101+
return Err.newErr("no such field: " + fieldName);
102+
}
103+
return DefaultTypeAdapter.Instance.nativeToValue(message.getField(field));
104+
});
105+
}
106+
78107
/**
79108
* Creates a custom binary function overload for the "format" operation.
80109
*

0 commit comments

Comments
 (0)