Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions runtime/src/main/java/dev/cel/runtime/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ java_library(
deps = [
":evaluation_exception",
":evaluation_exception_builder",
":function_binding",
":function_overload",
":function_resolver",
":resolved_overload",
Expand All @@ -141,6 +142,7 @@ cel_android_library(
deps = [
":evaluation_exception",
":evaluation_exception_builder",
":function_binding_android",
":function_overload_android",
":function_resolver_android",
":resolved_overload_android",
Expand Down Expand Up @@ -609,6 +611,7 @@ java_library(
deps = [
":function_binding",
":runtime_equality",
"//common:operator",
"//common:options",
"//common/annotations",
"//runtime/standard:add",
Expand Down Expand Up @@ -666,6 +669,7 @@ cel_android_library(
deps = [
":function_binding_android",
":runtime_equality_android",
"//common:operator_android",
"//common:options",
"//common/annotations",
"//runtime/standard:add_android",
Expand Down Expand Up @@ -723,6 +727,7 @@ java_library(
tags = [
],
deps = [
":evaluation_exception",
":function_overload",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
Expand All @@ -735,6 +740,7 @@ cel_android_library(
tags = [
],
deps = [
":evaluation_exception",
":function_overload_android",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven_android//:com_google_guava_guava",
Expand Down Expand Up @@ -774,7 +780,9 @@ java_library(
],
deps = [
":evaluation_exception",
"//runtime:unknown_attributes",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
],
)

Expand All @@ -785,7 +793,9 @@ cel_android_library(
],
deps = [
":evaluation_exception",
"//runtime:unknown_attributes_android",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven_android//:com_google_guava_guava",
],
)

Expand Down Expand Up @@ -1173,7 +1183,6 @@ java_library(
],
deps = [
":function_overload",
":unknown_attributes",
"//:auto_value",
"//common/annotations",
"@maven//:com_google_errorprone_error_prone_annotations",
Expand All @@ -1188,7 +1197,6 @@ cel_android_library(
],
deps = [
":function_overload_android",
":unknown_attributes_android",
"//:auto_value",
"//common/annotations",
"@maven//:com_google_errorprone_error_prone_annotations",
Expand Down
25 changes: 24 additions & 1 deletion runtime/src/main/java/dev/cel/runtime/CelFunctionBinding.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@

package dev.cel.runtime;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.errorprone.annotations.Immutable;
import java.util.Collection;

/**
* Binding consisting of an overload id, a Java-native argument signature, and an overload
Expand All @@ -35,7 +40,6 @@
*
* <p>Examples: string_startsWith_string, mathMax_list, lessThan_money_money
*/

@Immutable
public interface CelFunctionBinding {
String getOverloadId();
Expand Down Expand Up @@ -70,4 +74,23 @@ static CelFunctionBinding from(
return new FunctionBindingImpl(
overloadId, ImmutableList.copyOf(argTypes), impl, /* isStrict= */ true);
}

/** See {@link #fromOverloads(String, Collection)}. */
static ImmutableSet<CelFunctionBinding> fromOverloads(
String functionName, CelFunctionBinding... overloadBindings) {
return fromOverloads(functionName, ImmutableList.copyOf(overloadBindings));
}

/**
* Creates a set of bindings for a function, enabling dynamic dispatch logic to select the correct
* overload at runtime based on argument types.
*/
static ImmutableSet<CelFunctionBinding> fromOverloads(
String functionName, Collection<CelFunctionBinding> overloadBindings) {
checkArgument(!Strings.isNullOrEmpty(functionName), "Function name cannot be null or empty");
checkArgument(!overloadBindings.isEmpty(), "You must provide at least one binding.");

return FunctionBindingImpl.groupOverloadsToFunction(
functionName, ImmutableSet.copyOf(overloadBindings));
}
}
37 changes: 37 additions & 0 deletions runtime/src/main/java/dev/cel/runtime/CelFunctionOverload.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

package dev.cel.runtime;

import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.Immutable;
import java.util.Map;

/** Interface describing the general signature of all CEL custom function implementations. */
@Immutable
Expand Down Expand Up @@ -43,4 +45,39 @@ interface Unary<T> {
interface Binary<T1, T2> {
Object apply(T1 arg1, T2 arg2) throws CelEvaluationException;
}

/**
* Returns true if the overload's expected argument types match the types of the given arguments.
*/
static boolean canHandle(
Object[] arguments, ImmutableList<Class<?>> parameterTypes, boolean isStrict) {
if (parameterTypes.size() != arguments.length) {
return false;
}
for (int i = 0; i < parameterTypes.size(); i++) {
Class<?> paramType = parameterTypes.get(i);
Object arg = arguments[i];
if (arg == null) {
// null can be assigned to messages, maps, and to objects.
// TODO: Remove null special casing
if (paramType != Object.class && !Map.class.isAssignableFrom(paramType)) {
return false;
}
continue;
}

if (arg instanceof Exception || arg instanceof CelUnknownSet) {
// Only non-strict functions can accept errors/unknowns as arguments to a function
if (!isStrict) {
// Skip assignability check below, but continue to validate remaining args
continue;
}
}

if (!paramType.isAssignableFrom(arg.getClass())) {
return false;
}
}
return true;
}
}
38 changes: 1 addition & 37 deletions runtime/src/main/java/dev/cel/runtime/CelResolvedOverload.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.google.errorprone.annotations.Immutable;
import dev.cel.common.annotations.Internal;
import java.util.List;
import java.util.Map;

/**
* Representation of a function overload which has been resolved to a specific set of argument types
Expand Down Expand Up @@ -80,41 +79,6 @@ public static CelResolvedOverload of(
* Returns true if the overload's expected argument types match the types of the given arguments.
*/
boolean canHandle(Object[] arguments) {
return canHandle(arguments, getParameterTypes(), isStrict());
}

/**
* Returns true if the overload's expected argument types match the types of the given arguments.
*/
public static boolean canHandle(
Object[] arguments, ImmutableList<Class<?>> parameterTypes, boolean isStrict) {
if (parameterTypes.size() != arguments.length) {
return false;
}
for (int i = 0; i < parameterTypes.size(); i++) {
Class<?> paramType = parameterTypes.get(i);
Object arg = arguments[i];
if (arg == null) {
// null can be assigned to messages, maps, and to objects.
// TODO: Remove null special casing
if (paramType != Object.class && !Map.class.isAssignableFrom(paramType)) {
return false;
}
continue;
}

if (arg instanceof Exception || arg instanceof CelUnknownSet) {
// Only non-strict functions can accept errors/unknowns as arguments to a function
if (!isStrict) {
// Skip assignability check below, but continue to validate remaining args
continue;
}
}

if (!paramType.isAssignableFrom(arg.getClass())) {
return false;
}
}
return true;
return CelFunctionOverload.canHandle(arguments, getParameterTypes(), isStrict());
}
}
Loading
Loading