Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add string to boolean conversion function in the standard definition #407

Merged
merged 1 commit into from
Aug 2, 2024
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
4 changes: 3 additions & 1 deletion checker/src/main/java/dev/cel/checker/Standard.java
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,9 @@ private static ImmutableList<CelFunctionDecl> coreFunctionDeclarations() {
CelFunctionDecl.newFunctionDeclaration(
Function.BOOL.getFunction(),
CelOverloadDecl.newGlobalOverload(
"bool_to_bool", "type conversion (identity)", SimpleType.BOOL, SimpleType.BOOL)));
"bool_to_bool", "type conversion (identity)", SimpleType.BOOL, SimpleType.BOOL),
CelOverloadDecl.newGlobalOverload(
"string_to_bool", "type conversion", SimpleType.BOOL, SimpleType.STRING)));

// String functions
celFunctionDeclBuilder.add(
Expand Down
1 change: 1 addition & 0 deletions checker/src/test/resources/standardEnvDump.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ declare _||_ {
declare bool {
value type(bool)
function bool_to_bool (bool) -> bool
function string_to_bool (string) -> bool
}
declare bytes {
value type(bytes)
Expand Down
27 changes: 27 additions & 0 deletions runtime/src/main/java/dev/cel/runtime/StandardFunctions.java
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,33 @@ public static void addNonInlined(
private static void addBoolFunctions(Registrar registrar) {
// Identity
registrar.add("bool_to_bool", Boolean.class, (Boolean x) -> x);
// Conversion function
registrar.add(
"string_to_bool",
String.class,
(String str) -> {
// Note: this is a bit less permissive than what cel-go allows (it accepts '1', 't').
switch (str) {
case "true":
case "TRUE":
case "True":
case "t":
case "1":
return true;
case "false":
case "FALSE":
case "False":
case "f":
case "0":
return false;
default:
throw new InterpreterException.Builder(
"Type conversion error from 'string' to 'bool': [%s]", str)
.setErrorCode(CelErrorCode.BAD_FORMAT)
.build();
}
});

// The conditional, logical_or, logical_and, and not_strictly_false functions are special-cased.
registrar.add("logical_not", Boolean.class, (Boolean x) -> !x);

Expand Down
24 changes: 23 additions & 1 deletion runtime/src/test/resources/boolConversions.baseline
Original file line number Diff line number Diff line change
@@ -1,4 +1,26 @@
Source: bool(true)
=====>
bindings: {}
result: true
result: true

Source: bool('true') && bool('TRUE') && bool('True') && bool('t') && bool('1')
=====>
bindings: {}
result: true

Source: bool('false') || bool('FALSE') || bool('False') || bool('f') || bool('0')
=====>
bindings: {}
result: false

Source: bool('TrUe')
=====>
bindings: {}
error: evaluation error: Type conversion error from 'string' to 'bool': [TrUe]
error_code: BAD_FORMAT

Source: bool('FaLsE')
=====>
bindings: {}
error: evaluation error: Type conversion error from 'string' to 'bool': [FaLsE]
error_code: BAD_FORMAT
12 changes: 12 additions & 0 deletions testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1568,6 +1568,18 @@ public void bytes() throws Exception {
public void boolConversions() throws Exception {
source = "bool(true)";
runTest(Activation.EMPTY); // Identity

source = "bool('true') && bool('TRUE') && bool('True') && bool('t') && bool('1')";
runTest(Activation.EMPTY); // result is true

source = "bool('false') || bool('FALSE') || bool('False') || bool('f') || bool('0')";
runTest(Activation.EMPTY); // result is false

source = "bool('TrUe')";
runTest(Activation.EMPTY); // exception

source = "bool('FaLsE')";
runTest(Activation.EMPTY); // exception
}

@Test
Expand Down
Loading