pub enum Value {
Show 16 variants
Null,
Bool(bool),
Int(i64),
UInt(u64),
Double(f64),
String(Arc<str>),
Bytes(Arc<[u8]>),
List(Arc<[Value]>),
Map(Arc<ValueMap>),
Timestamp(Timestamp),
Duration(Duration),
Type(TypeValue),
Optional(OptionalValue),
Message(Box<dyn MessageValue>),
Enum(EnumValue),
Error(Arc<EvalError>),
}Expand description
A CEL runtime value.
This enum represents all possible values that can exist during CEL evaluation.
Unlike CelValue (which represents compile-time constants), Value supports
the full range of CEL types including collections, timestamps, and errors.
Variants§
Null
Null value.
Bool(bool)
Boolean value.
Int(i64)
Signed 64-bit integer.
UInt(u64)
Unsigned 64-bit integer.
Double(f64)
64-bit floating point.
String(Arc<str>)
Unicode string (Arc for cheap cloning).
Bytes(Arc<[u8]>)
Byte sequence (Arc for cheap cloning).
List(Arc<[Value]>)
Homogeneous list.
Map(Arc<ValueMap>)
Key-value map (uses BTreeMap for deterministic iteration).
Timestamp(Timestamp)
Timestamp (seconds and nanos since Unix epoch).
Duration(Duration)
Duration (seconds and nanos).
Type(TypeValue)
Type value (represents a CEL type at runtime).
Optional(OptionalValue)
Optional value (present or absent).
Message(Box<dyn MessageValue>)
Protobuf message value.
Enum(EnumValue)
Enum value with type information (strong enum typing).
Error(Arc<EvalError>)
Error value (evaluation errors propagate as values).
Implementations§
Source§impl Value
impl Value
Sourcepub fn map<K, V>(entries: impl IntoIterator<Item = (K, V)>) -> Self
pub fn map<K, V>(entries: impl IntoIterator<Item = (K, V)>) -> Self
Create a map value from key-value pairs.
Keys and values are automatically converted using Into<MapKey> and Into<Value>.
use cel_core::Value;
// String keys and values
let map = Value::map([("host", "localhost"), ("port", "8080")]);
// Integer keys
let map = Value::map([(1i64, "one"), (2i64, "two")]);
// Mixed value types require explicit Value construction
let map = Value::map([
("name", Value::from("Alice")),
("age", Value::from(30i64)),
]);Examples found in repository?
7fn main() {
8 let env = Env::with_standard_library()
9 .with_variable("user", CelType::map(CelType::String, CelType::Dyn));
10
11 // Mixed value types require explicit Value::from()
12 let user = Value::map([
13 ("name", Value::from("Alice")),
14 ("age", Value::from(30)), // i32 automatically widens to i64
15 ("active", Value::from(true)),
16 ]);
17
18 let mut activation = MapActivation::new();
19 activation.insert("user", user);
20
21 // Field access
22 let ast = env.compile("user.name").unwrap();
23 let program = env.program(&ast).unwrap();
24 let result = program.eval(&activation);
25 println!("user.name: {}", result);
26
27 // Index access
28 let ast = env.compile(r#"user["age"]"#).unwrap();
29 let program = env.program(&ast).unwrap();
30 let result = program.eval(&activation);
31 println!(r#"user["age"]: {}"#, result);
32
33 // Check field existence with 'in'
34 let ast = env.compile(r#""name" in user"#).unwrap();
35 let program = env.program(&ast).unwrap();
36 let result = program.eval(&activation);
37 println!(r#""name" in user: {}"#, result);
38
39 // Check field existence with has()
40 let ast = env.compile("has(user.email)").unwrap();
41 let program = env.program(&ast).unwrap();
42 let result = program.eval(&activation);
43 println!("has(user.email): {}", result);
44
45 // Combine conditions
46 let ast = env.compile(r#"user.active && user.age >= 21"#).unwrap();
47 let program = env.program(&ast).unwrap();
48 let result = program.eval(&activation);
49 println!("active && age >= 21: {}", result);
50}More examples
7fn main() {
8 let env = Env::with_standard_library()
9 .with_variable("x", CelType::Int)
10 .with_variable("items", CelType::list(CelType::Int));
11
12 let mut activation = MapActivation::new();
13
14 // Division by zero returns an error value
15 println!("=== Division by zero ===");
16 activation.insert("x", 0);
17 let ast = env.compile("10 / x").unwrap();
18 let program = env.program(&ast).unwrap();
19 let result = program.eval(&activation);
20
21 match &result {
22 Value::Error(err) => println!("Error: {}", err),
23 other => println!("Result: {}", other),
24 }
25
26 // Index out of bounds
27 println!("\n=== Index out of bounds ===");
28 activation.insert("items", Value::list([1, 2, 3]));
29 let ast = env.compile("items[10]").unwrap();
30 let program = env.program(&ast).unwrap();
31 let result = program.eval(&activation);
32
33 match &result {
34 Value::Error(err) => println!("Error: {}", err),
35 other => println!("Result: {}", other),
36 }
37
38 // Key not found in map
39 println!("\n=== Key not found ===");
40 let env = Env::with_standard_library()
41 .with_variable("config", CelType::map(CelType::String, CelType::String));
42 let mut activation = MapActivation::new();
43 activation.insert("config", Value::map([("host", "localhost")]));
44
45 let ast = env.compile("config.missing_key").unwrap();
46 let program = env.program(&ast).unwrap();
47 let result = program.eval(&activation);
48
49 match &result {
50 Value::Error(err) => println!("Error: {}", err),
51 other => println!("Result: {}", other),
52 }
53
54 // Use has() to safely check field existence
55 println!("\n=== Safe field access with has() ===");
56 let ast = env
57 .compile("has(config.missing_key) ? config.missing_key : 'default'")
58 .unwrap();
59 let program = env.program(&ast).unwrap();
60 let result = program.eval(&activation);
61 println!("Result: {}", result);
62}7fn main() {
8 let env = Env::with_standard_library()
9 .with_variable("count", CelType::Int)
10 .with_variable("items", CelType::list(CelType::Int))
11 .with_variable("config", CelType::map(CelType::String, CelType::String));
12
13 let mut activation = MapActivation::new();
14 activation.insert("count", 42); // i32 automatically widens to i64
15 activation.insert("items", Value::list([1, 2, 3]));
16 activation.insert(
17 "config",
18 Value::map([("host", "localhost"), ("port", "8080")]),
19 );
20
21 // Extract i64
22 let ast = env.compile("count * 2").unwrap();
23 let program = env.program(&ast).unwrap();
24 let result = program.eval(&activation);
25
26 let value: i64 = (&result).try_into().expect("expected int");
27 println!("i64: {}", value);
28
29 // Extract bool
30 let ast = env.compile("count > 10").unwrap();
31 let program = env.program(&ast).unwrap();
32 let result = program.eval(&activation);
33
34 let value: bool = (&result).try_into().expect("expected bool");
35 println!("bool: {}", value);
36
37 // Extract &str
38 let ast = env.compile("config.host").unwrap();
39 let program = env.program(&ast).unwrap();
40 let result = program.eval(&activation);
41
42 let value: &str = (&result).try_into().expect("expected string");
43 println!("&str: {}", value);
44
45 // Extract &[Value] (list)
46 let ast = env.compile("items.filter(x, x > 1)").unwrap();
47 let program = env.program(&ast).unwrap();
48 let result = program.eval(&activation);
49
50 let list: &[Value] = (&result).try_into().expect("expected list");
51 println!("list length: {}", list.len());
52 for (i, v) in list.iter().enumerate() {
53 let n: i64 = v.try_into().expect("expected int");
54 println!(" [{}] = {}", i, n);
55 }
56
57 // Extract &ValueMap
58 let ast = env.compile("config").unwrap();
59 let program = env.program(&ast).unwrap();
60 let result = program.eval(&activation);
61
62 let map: &ValueMap = (&result).try_into().expect("expected map");
63 println!("map size: {}", map.len());
64 for (k, v) in map.iter() {
65 println!(" {:?} = {}", k, v);
66 }
67
68 // Handle errors gracefully
69 let result = Value::from("not an int");
70 let attempt: Result<i64, _> = (&result).try_into();
71 match attempt {
72 Ok(v) => println!("got: {}", v),
73 Err(e) => println!("conversion error: {}", e),
74 }
75
76 // Extract &OptionalValue
77 let opt_result = Value::optional_some(Value::from(99));
78 let opt: &OptionalValue = (&opt_result).try_into().expect("expected optional");
79 if opt.is_present() {
80 let inner: i64 = opt.as_value().unwrap().try_into().expect("expected int");
81 println!("optional value: {}", inner);
82 }
83}Sourcepub fn list<T>(items: impl IntoIterator<Item = T>) -> Self
pub fn list<T>(items: impl IntoIterator<Item = T>) -> Self
Create a list value from items.
Items are automatically converted using Into<Value>.
use cel_core::Value;
// Integer list (no i64 suffix needed)
let list = Value::list([1, 2, 3]);
// String list
let list = Value::list(["a", "b", "c"]);
// Mixed types require explicit Value construction
let list = Value::list([Value::from(1), Value::from("two")]);Examples found in repository?
7fn main() {
8 let env = Env::with_standard_library().with_variable("numbers", CelType::list(CelType::Int));
9
10 let mut activation = MapActivation::new();
11 activation.insert("numbers", Value::list([1, 5, 3, 8, 2]));
12
13 // Filter: keep only values > 3
14 let ast = env.compile("numbers.filter(x, x > 3)").unwrap();
15 let program = env.program(&ast).unwrap();
16 let result = program.eval(&activation);
17 println!("filter(x, x > 3): {}", result);
18
19 // Map: double each value
20 let ast = env.compile("numbers.map(x, x * 2)").unwrap();
21 let program = env.program(&ast).unwrap();
22 let result = program.eval(&activation);
23 println!("map(x, x * 2): {}", result);
24
25 // Exists: any value > 7?
26 let ast = env.compile("numbers.exists(x, x > 7)").unwrap();
27 let program = env.program(&ast).unwrap();
28 let result = program.eval(&activation);
29 println!("exists(x, x > 7): {}", result);
30
31 // All: all values > 0?
32 let ast = env.compile("numbers.all(x, x > 0)").unwrap();
33 let program = env.program(&ast).unwrap();
34 let result = program.eval(&activation);
35 println!("all(x, x > 0): {}", result);
36
37 // Size
38 let ast = env.compile("numbers.size()").unwrap();
39 let program = env.program(&ast).unwrap();
40 let result = program.eval(&activation);
41 println!("size(): {}", result);
42
43 // Contains (using 'in' operator)
44 let ast = env.compile("5 in numbers").unwrap();
45 let program = env.program(&ast).unwrap();
46 let result = program.eval(&activation);
47 println!("5 in numbers: {}", result);
48}More examples
7fn main() {
8 let env = Env::with_standard_library()
9 .with_variable("x", CelType::Int)
10 .with_variable("items", CelType::list(CelType::Int));
11
12 let mut activation = MapActivation::new();
13
14 // Division by zero returns an error value
15 println!("=== Division by zero ===");
16 activation.insert("x", 0);
17 let ast = env.compile("10 / x").unwrap();
18 let program = env.program(&ast).unwrap();
19 let result = program.eval(&activation);
20
21 match &result {
22 Value::Error(err) => println!("Error: {}", err),
23 other => println!("Result: {}", other),
24 }
25
26 // Index out of bounds
27 println!("\n=== Index out of bounds ===");
28 activation.insert("items", Value::list([1, 2, 3]));
29 let ast = env.compile("items[10]").unwrap();
30 let program = env.program(&ast).unwrap();
31 let result = program.eval(&activation);
32
33 match &result {
34 Value::Error(err) => println!("Error: {}", err),
35 other => println!("Result: {}", other),
36 }
37
38 // Key not found in map
39 println!("\n=== Key not found ===");
40 let env = Env::with_standard_library()
41 .with_variable("config", CelType::map(CelType::String, CelType::String));
42 let mut activation = MapActivation::new();
43 activation.insert("config", Value::map([("host", "localhost")]));
44
45 let ast = env.compile("config.missing_key").unwrap();
46 let program = env.program(&ast).unwrap();
47 let result = program.eval(&activation);
48
49 match &result {
50 Value::Error(err) => println!("Error: {}", err),
51 other => println!("Result: {}", other),
52 }
53
54 // Use has() to safely check field existence
55 println!("\n=== Safe field access with has() ===");
56 let ast = env
57 .compile("has(config.missing_key) ? config.missing_key : 'default'")
58 .unwrap();
59 let program = env.program(&ast).unwrap();
60 let result = program.eval(&activation);
61 println!("Result: {}", result);
62}7fn main() {
8 let env = Env::with_standard_library()
9 .with_variable("count", CelType::Int)
10 .with_variable("items", CelType::list(CelType::Int))
11 .with_variable("config", CelType::map(CelType::String, CelType::String));
12
13 let mut activation = MapActivation::new();
14 activation.insert("count", 42); // i32 automatically widens to i64
15 activation.insert("items", Value::list([1, 2, 3]));
16 activation.insert(
17 "config",
18 Value::map([("host", "localhost"), ("port", "8080")]),
19 );
20
21 // Extract i64
22 let ast = env.compile("count * 2").unwrap();
23 let program = env.program(&ast).unwrap();
24 let result = program.eval(&activation);
25
26 let value: i64 = (&result).try_into().expect("expected int");
27 println!("i64: {}", value);
28
29 // Extract bool
30 let ast = env.compile("count > 10").unwrap();
31 let program = env.program(&ast).unwrap();
32 let result = program.eval(&activation);
33
34 let value: bool = (&result).try_into().expect("expected bool");
35 println!("bool: {}", value);
36
37 // Extract &str
38 let ast = env.compile("config.host").unwrap();
39 let program = env.program(&ast).unwrap();
40 let result = program.eval(&activation);
41
42 let value: &str = (&result).try_into().expect("expected string");
43 println!("&str: {}", value);
44
45 // Extract &[Value] (list)
46 let ast = env.compile("items.filter(x, x > 1)").unwrap();
47 let program = env.program(&ast).unwrap();
48 let result = program.eval(&activation);
49
50 let list: &[Value] = (&result).try_into().expect("expected list");
51 println!("list length: {}", list.len());
52 for (i, v) in list.iter().enumerate() {
53 let n: i64 = v.try_into().expect("expected int");
54 println!(" [{}] = {}", i, n);
55 }
56
57 // Extract &ValueMap
58 let ast = env.compile("config").unwrap();
59 let program = env.program(&ast).unwrap();
60 let result = program.eval(&activation);
61
62 let map: &ValueMap = (&result).try_into().expect("expected map");
63 println!("map size: {}", map.len());
64 for (k, v) in map.iter() {
65 println!(" {:?} = {}", k, v);
66 }
67
68 // Handle errors gracefully
69 let result = Value::from("not an int");
70 let attempt: Result<i64, _> = (&result).try_into();
71 match attempt {
72 Ok(v) => println!("got: {}", v),
73 Err(e) => println!("conversion error: {}", e),
74 }
75
76 // Extract &OptionalValue
77 let opt_result = Value::optional_some(Value::from(99));
78 let opt: &OptionalValue = (&opt_result).try_into().expect("expected optional");
79 if opt.is_present() {
80 let inner: i64 = opt.as_value().unwrap().try_into().expect("expected int");
81 println!("optional value: {}", inner);
82 }
83}Sourcepub fn optional_none() -> Self
pub fn optional_none() -> Self
Create an optional none value.
Sourcepub fn optional_some(value: Value) -> Self
pub fn optional_some(value: Value) -> Self
Create an optional some value.
Examples found in repository?
7fn main() {
8 let env = Env::with_standard_library()
9 .with_variable("count", CelType::Int)
10 .with_variable("items", CelType::list(CelType::Int))
11 .with_variable("config", CelType::map(CelType::String, CelType::String));
12
13 let mut activation = MapActivation::new();
14 activation.insert("count", 42); // i32 automatically widens to i64
15 activation.insert("items", Value::list([1, 2, 3]));
16 activation.insert(
17 "config",
18 Value::map([("host", "localhost"), ("port", "8080")]),
19 );
20
21 // Extract i64
22 let ast = env.compile("count * 2").unwrap();
23 let program = env.program(&ast).unwrap();
24 let result = program.eval(&activation);
25
26 let value: i64 = (&result).try_into().expect("expected int");
27 println!("i64: {}", value);
28
29 // Extract bool
30 let ast = env.compile("count > 10").unwrap();
31 let program = env.program(&ast).unwrap();
32 let result = program.eval(&activation);
33
34 let value: bool = (&result).try_into().expect("expected bool");
35 println!("bool: {}", value);
36
37 // Extract &str
38 let ast = env.compile("config.host").unwrap();
39 let program = env.program(&ast).unwrap();
40 let result = program.eval(&activation);
41
42 let value: &str = (&result).try_into().expect("expected string");
43 println!("&str: {}", value);
44
45 // Extract &[Value] (list)
46 let ast = env.compile("items.filter(x, x > 1)").unwrap();
47 let program = env.program(&ast).unwrap();
48 let result = program.eval(&activation);
49
50 let list: &[Value] = (&result).try_into().expect("expected list");
51 println!("list length: {}", list.len());
52 for (i, v) in list.iter().enumerate() {
53 let n: i64 = v.try_into().expect("expected int");
54 println!(" [{}] = {}", i, n);
55 }
56
57 // Extract &ValueMap
58 let ast = env.compile("config").unwrap();
59 let program = env.program(&ast).unwrap();
60 let result = program.eval(&activation);
61
62 let map: &ValueMap = (&result).try_into().expect("expected map");
63 println!("map size: {}", map.len());
64 for (k, v) in map.iter() {
65 println!(" {:?} = {}", k, v);
66 }
67
68 // Handle errors gracefully
69 let result = Value::from("not an int");
70 let attempt: Result<i64, _> = (&result).try_into();
71 match attempt {
72 Ok(v) => println!("got: {}", v),
73 Err(e) => println!("conversion error: {}", e),
74 }
75
76 // Extract &OptionalValue
77 let opt_result = Value::optional_some(Value::from(99));
78 let opt: &OptionalValue = (&opt_result).try_into().expect("expected optional");
79 if opt.is_present() {
80 let inner: i64 = opt.as_value().unwrap().try_into().expect("expected int");
81 println!("optional value: {}", inner);
82 }
83}Sourcepub fn from_option<T: Into<Value>>(opt: Option<T>) -> Self
pub fn from_option<T: Into<Value>>(opt: Option<T>) -> Self
Convert an Option
Unlike From<Option<T>> which maps None to Value::Null,
this preserves CEL optional semantics.
use cel_core::Value;
let some_val = Value::from_option(Some(42)); // optional.of(42)
let none_val = Value::from_option(None::<i32>); // optional.none()