Skip to main content

functions/
functions.rs

1#![allow(clippy::too_many_arguments)]
2use std::sync::Arc;
3
4use bel::{Context, ExecutionError, FunctionContext, Program, ResolveResult, Value, extractors::This};
5use chrono::{DateTime, Duration, FixedOffset};
6
7fn main() {
8    let program = Program::compile("add(2, 3) == 5 && ''.isEmpty() && fail()").unwrap();
9    let mut context = Context::default();
10
11    // Add functions using closures
12    context.add_function("add", |a: i64, b: i64| a + b);
13
14    // Add methods to a string type
15    context.add_function("isEmpty", is_empty);
16
17    // Use the function context to return error messages
18    context.add_function("fail", fail);
19
20    // See all the different value types you can accept in your functions
21    // context.add_function("primitives", primitives);
22
23    // Run the program
24    let result = program.execute(&context);
25    assert!(matches!(result, Err(ExecutionError::FunctionError { .. })));
26}
27
28/// A method on a string type. When added to the CEL context, this function
29/// can be called by running. We use the [`This`] extractor give us a reference
30/// to the string that this method was called on.
31///
32/// ```skip
33/// "foo".isEmpty()
34/// ```
35fn is_empty(This(s): This<Arc<String>>) -> bool {
36    s.is_empty()
37}
38
39/// A function that gives us access to the [`FunctionContext`]. All functions have
40/// can accept this context as their first argument. The context is helpful for
41/// several reasons:
42/// 1. Creating shadowed variables using cloned contexts (see the `filter` and `map`
43///    functions for example).
44/// 2. Functions that are fallible can return an error message using ftx.error(...)
45///    which attaches some helpful context for the error.
46fn fail(ftx: &FunctionContext) -> ResolveResult {
47    ftx.error("This function always fails").into()
48}
49
50/// A function that illustrates all the different types of values that are supported
51/// as arguments to a function, as well as the fact that any of these types can also
52/// be returned from a function.
53fn primitives(
54    _a: i64,
55    _b: u64,
56    _c: f64,
57    _d: bool,
58    _e: Arc<String>,
59    _f: Arc<Vec<u8>>,
60    _g: Duration,
61    _h: DateTime<FixedOffset>,
62    _i: Arc<Vec<Value>>,
63) -> Duration {
64    Duration::zero()
65}