pub struct EnvBuilder<'f, Fm: FnMarker = (), Rm: RuntimeMarker = ()> { /* private fields */ }
Expand description
Builder for creating CEL environments.
The EnvBuilder
allows you to configure a CEL environment by registering
functions, declaring variables, and setting up runtime options before
building the final environment.
§Type Parameters
'f
: Lifetime of functions that will be registeredFm
: Function marker type indicating sync/async function supportRm
: Runtime marker type indicating the async runtime (if any)
§Examples
use cel_cxx::*;
let env = Env::builder()
.register_global_function("double", |x: i64| -> i64 { x * 2 })?
.declare_variable::<String>("message")?
.build()?;
Implementations§
Source§impl<'f, Fm: FnMarker, Rm: RuntimeMarker> EnvBuilder<'f, Fm, Rm>
impl<'f, Fm: FnMarker, Rm: RuntimeMarker> EnvBuilder<'f, Fm, Rm>
Source§impl<'f, Fm: FnMarker, Rm: RuntimeMarker> EnvBuilder<'f, Fm, Rm>
impl<'f, Fm: FnMarker, Rm: RuntimeMarker> EnvBuilder<'f, Fm, Rm>
Sourcepub fn register_function<F, Ffm, Args>(
self,
name: impl Into<String>,
member: bool,
f: F,
) -> Result<EnvBuilder<'f, <Ffm as FnMarkerAggr<Fm>>::Output, Rm>, Error>
pub fn register_function<F, Ffm, Args>( self, name: impl Into<String>, member: bool, f: F, ) -> Result<EnvBuilder<'f, <Ffm as FnMarkerAggr<Fm>>::Output, Rm>, Error>
Registers a function (either global or member).
This method allows you to register custom functions that can be called from CEL expressions. The function can be either a global function or a member function of a type.
§Function Registration Process
When you register a function, the system:
- Extracts type information from the function signature
- Creates type-safe conversion wrappers
- Stores both the type signature and implementation
- Updates the function marker type to track sync/async status
§Zero-Annotation Benefits
Functions are registered without explicit type annotations:
- Argument types are automatically inferred
- Return types are automatically determined
- Error handling is automatically supported for
Result<T, E>
returns - Reference parameters like
&str
are handled safely
§Arguments
name
- The name of the function as it will appear in CEL expressionsmember
- Whether this is a member function (true
) or global function (false
)f
- The function implementation (function pointer, closure, etc.)
§Type Parameters
F
- The function implementation typeFfm
- The function marker type (sync/async) inferred from the functionArgs
- The argument tuple type (automatically inferred)
§Returns
A new EnvBuilder
with updated function marker type. If this is the first
async function registered, the marker changes from ()
to Async
.
§Member vs Global Functions
§Global Functions
Called as function_name(args...)
:
max(a, b) // max function with two arguments
calculate(x, y, z) // calculate function with three arguments
§Member Functions
Called as object.method(args...)
:
text.contains(substring) // contains method on string
list.size() // size method on list
§Function Signature Support
Supports various function signatures:
- Simple functions:
fn(T) -> U
- Functions with errors:
fn(T) -> Result<U, E>
- Reference parameters:
fn(&str, i64) -> String
- Multiple parameters: Up to 10 parameters supported
- Closures: Move closures that capture environment
§Errors
Returns Error
if:
- Function name conflicts with existing registration
- Function signature is invalid or unsupported
- Type inference fails
§Examples
§Basic Functions
use cel_cxx::*;
let builder = Env::builder()
.register_function("add", false, |a: i64, b: i64| a + b)?
.register_function("greet", false, |name: &str| format!("Hello, {}!", name))?;
§Member Functions
use cel_cxx::*;
let builder = Env::builder()
.register_function("contains", true, |text: &str, substr: &str| text.contains(substr))?
.register_function("length", true, |text: &str| text.len() as i64)?;
// Usage in expressions:
// text.contains("hello")
// text.length()
§Functions with Error Handling
use cel_cxx::*;
let builder = Env::builder()
.register_function("divide", false, |a: f64, b: f64| -> Result<f64, Error> {
if b == 0.0 {
Err(Error::invalid_argument("division by zero"))
} else {
Ok(a / b)
}
})?;
§Closures with Captured Data
use cel_cxx::*;
let multiplier = 5;
let threshold = 100.0;
let builder = Env::builder()
.register_function("scale", false, move |x: i64| x * multiplier)?
.register_function("check_limit", false, move |value: f64| value < threshold)?;
Sourcepub fn register_member_function<F, Ffm, Args>(
self,
name: impl Into<String>,
f: F,
) -> Result<EnvBuilder<'f, <Ffm as FnMarkerAggr<Fm>>::Output, Rm>, Error>
pub fn register_member_function<F, Ffm, Args>( self, name: impl Into<String>, f: F, ) -> Result<EnvBuilder<'f, <Ffm as FnMarkerAggr<Fm>>::Output, Rm>, Error>
Registers a member function.
This is a convenience method for registering member functions, equivalent to
calling register_function(name, true, f)
. Member functions are called using
dot notation in CEL expressions: object.method(args...)
.
§Arguments
name
- The method name as it will appear in CEL expressionsf
- The function implementation
§Member Function Semantics
Member functions in CEL follow these patterns:
- First parameter is the “receiver” (the object before the dot)
- Additional parameters become method arguments
- Called as
receiver.method(arg1, arg2, ...)
§Examples
§String Methods
use cel_cxx::*;
let builder = Env::builder()
.register_member_function("upper", |s: &str| s.to_uppercase())?
.register_member_function("contains", |s: &str, substr: &str| s.contains(substr))?
.register_member_function("repeat", |s: &str, n: i64| s.repeat(n as usize))?;
// Usage in expressions:
// "hello".upper() -> "HELLO"
// "hello world".contains("world") -> true
// "abc".repeat(3) -> "abcabcabc"
§Numeric Methods
use cel_cxx::*;
let builder = Env::builder()
.register_member_function("abs", |x: f64| x.abs())?
.register_member_function("pow", |x: f64, exp: f64| x.powf(exp))?;
// Usage in expressions:
// (-5.5).abs() -> 5.5
// (2.0).pow(3.0) -> 8.0
Sourcepub fn register_global_function<F, Ffm, Args>(
self,
name: impl Into<String>,
f: F,
) -> Result<EnvBuilder<'f, <Ffm as FnMarkerAggr<Fm>>::Output, Rm>, Error>
pub fn register_global_function<F, Ffm, Args>( self, name: impl Into<String>, f: F, ) -> Result<EnvBuilder<'f, <Ffm as FnMarkerAggr<Fm>>::Output, Rm>, Error>
Registers a global function.
This is a convenience method for registering global functions, equivalent to
calling register_function(name, false, f)
. Global functions are called directly
by name in CEL expressions: function_name(args...)
.
§Arguments
name
- The function name as it will appear in CEL expressionsf
- The function implementation
§Global Function Characteristics
Global functions:
- Are called directly by name without a receiver object
- Can have 0 to 10 parameters
- Support all CEL-compatible parameter and return types
- Can capture environment variables (for closures)
§Function Naming Guidelines
- Use clear, descriptive names:
calculate_tax
,format_date
- Follow CEL naming conventions (snake_case is recommended)
- Avoid conflicts with built-in CEL functions
- Consider namespacing for domain-specific functions:
math_sqrt
,string_trim
§Examples
§Mathematical Functions
use cel_cxx::*;
let builder = Env::builder()
.register_global_function("add", |a: i64, b: i64| a + b)?
.register_global_function("multiply", |a: f64, b: f64| a * b)?
.register_global_function("max", |a: i64, b: i64| if a > b { a } else { b })?;
// Usage in expressions:
// add(10, 20) -> 30
// multiply(2.5, 4.0) -> 10.0
// max(15, 8) -> 15
§String Processing Functions
use cel_cxx::*;
let builder = Env::builder()
.register_global_function("concat", |a: &str, b: &str| format!("{}{}", a, b))?
.register_global_function("trim_prefix", |s: &str, prefix: &str| {
s.strip_prefix(prefix).unwrap_or(s).to_string()
})?;
// Usage in expressions:
// concat("Hello, ", "World!") -> "Hello, World!"
// trim_prefix("prefixed_text", "prefixed_") -> "text"
§Business Logic Functions
use cel_cxx::*;
let builder = Env::builder()
.register_global_function("calculate_discount", |price: f64, rate: f64| {
price * (1.0 - rate.min(1.0).max(0.0))
})?
.register_global_function("is_valid_email", |email: &str| {
email.contains('@') && email.contains('.')
})?;
// Usage in expressions:
// calculate_discount(100.0, 0.15) -> 85.0
// is_valid_email("user@domain.com") -> true
§Functions with Complex Logic
use cel_cxx::*;
use std::collections::HashMap;
// Function that processes collections
let builder = Env::builder()
.register_global_function("sum_positive", |numbers: Vec<i64>| {
numbers.iter().filter(|&x| *x > 0).sum::<i64>()
})?;
// Usage in expressions:
// sum_positive([1, -2, 3, -4, 5]) -> 9
Sourcepub fn declare_function<D>(
self,
name: impl Into<String>,
member: bool,
) -> Result<Self, Error>where
D: FunctionDecl,
pub fn declare_function<D>(
self,
name: impl Into<String>,
member: bool,
) -> Result<Self, Error>where
D: FunctionDecl,
Declares a function signature without providing an implementation.
This is useful when you want to declare that a function exists for type checking purposes, but will provide the implementation later via activation bindings.
§Arguments
name
- The name of the functionmember
- Whether this is a member function (true
) or global function (false
)
§Type Parameters
D
- The function declaration type that specifies the signature
Sourcepub fn declare_member_function<D>(
self,
name: impl Into<String>,
) -> Result<Self, Error>where
D: FunctionDecl,
pub fn declare_member_function<D>(
self,
name: impl Into<String>,
) -> Result<Self, Error>where
D: FunctionDecl,
Sourcepub fn declare_global_function<D>(
self,
name: impl Into<String>,
) -> Result<Self, Error>where
D: FunctionDecl,
pub fn declare_global_function<D>(
self,
name: impl Into<String>,
) -> Result<Self, Error>where
D: FunctionDecl,
Sourcepub fn define_constant<T>(
self,
name: impl Into<String>,
value: T,
) -> Result<Self, Error>where
T: IntoConstant,
pub fn define_constant<T>(
self,
name: impl Into<String>,
value: T,
) -> Result<Self, Error>where
T: IntoConstant,
Sourcepub fn declare_variable<T>(self, name: impl Into<String>) -> Result<Self, Error>where
T: TypedValue,
pub fn declare_variable<T>(self, name: impl Into<String>) -> Result<Self, Error>where
T: TypedValue,
Declares a variable of a specific type.
This declares that a variable of the given name and type may be provided during evaluation. The actual value must be bound in the activation when evaluating expressions.
§Arguments
name
- The name of the variable
§Type Parameters
T
- The type of the variable
§Examples
use cel_cxx::*;
let builder = Env::builder()
.declare_variable::<String>("user_name")?
.declare_variable::<i64>("age")?;
Sourcepub fn build(self) -> Result<Env<'f, Fm, Rm>, Error>
pub fn build(self) -> Result<Env<'f, Fm, Rm>, Error>
Builds the environment from the configured builder.
This method consumes the builder and creates the final Env
instance
that can be used to compile CEL expressions.
§Returns
Returns a Result
containing the built Env
or an Error
if
the environment could not be created.
§Examples
use cel_cxx::*;
let env = Env::builder()
.declare_variable::<String>("name")?
.build()?;
§Errors
Returns an error if the environment configuration is invalid or if the underlying CEL environment cannot be created.
Source§impl<'f, Rm: RuntimeMarker> EnvBuilder<'f, (), Rm>
impl<'f, Rm: RuntimeMarker> EnvBuilder<'f, (), Rm>
Sourcepub fn force_async(self) -> EnvBuilder<'f, Async, Rm>
Available on crate feature async
only.
pub fn force_async(self) -> EnvBuilder<'f, Async, Rm>
async
only.Forces conversion to an async environment builder.
This method converts a synchronous environment builder to an asynchronous one, allowing it to register async functions and build async environments.
§Examples
use cel_cxx::*;
let async_builder = Env::builder().force_async();
Source§impl<'f, Fm: FnMarker> EnvBuilder<'f, Fm, ()>
impl<'f, Fm: FnMarker> EnvBuilder<'f, Fm, ()>
Sourcepub fn use_runtime<Rt: Runtime>(self) -> EnvBuilder<'f, Fm, Rt>
Available on crate feature async
only.
pub fn use_runtime<Rt: Runtime>(self) -> EnvBuilder<'f, Fm, Rt>
async
only.Sourcepub fn use_tokio(self) -> EnvBuilder<'f, Fm, Tokio>
Available on crate features async
and tokio
only.
pub fn use_tokio(self) -> EnvBuilder<'f, Fm, Tokio>
async
and tokio
only.Configures the builder to use the Tokio async runtime.
This is a convenience method for setting the runtime to Tokio.
Requires the tokio
feature to be enabled.
§Examples
use cel_cxx::*;
let builder = Env::builder().use_tokio();
Sourcepub fn use_async_std(self) -> EnvBuilder<'f, Fm, AsyncStd>
Available on crate features async
and async-std
only.
pub fn use_async_std(self) -> EnvBuilder<'f, Fm, AsyncStd>
async
and async-std
only.Configures the builder to use the async-std runtime.
This is a convenience method for setting the runtime to async-std.
Requires the async-std
feature to be enabled.
§Examples
use cel_cxx::*;
let builder = Env::builder().use_async_std();
Trait Implementations§
Source§impl<'f, Fm: FnMarker, Rm: RuntimeMarker> Debug for EnvBuilder<'f, Fm, Rm>
impl<'f, Fm: FnMarker, Rm: RuntimeMarker> Debug for EnvBuilder<'f, Fm, Rm>
Source§impl<'f, Fm: FnMarker, Rm: RuntimeMarker> Default for EnvBuilder<'f, Fm, Rm>
impl<'f, Fm: FnMarker, Rm: RuntimeMarker> Default for EnvBuilder<'f, Fm, Rm>
Auto Trait Implementations§
impl<'f, Fm, Rm> Freeze for EnvBuilder<'f, Fm, Rm>
impl<'f, Fm = (), Rm = ()> !RefUnwindSafe for EnvBuilder<'f, Fm, Rm>
impl<'f, Fm, Rm> Send for EnvBuilder<'f, Fm, Rm>
impl<'f, Fm, Rm> Sync for EnvBuilder<'f, Fm, Rm>
impl<'f, Fm, Rm> Unpin for EnvBuilder<'f, Fm, Rm>
impl<'f, Fm = (), Rm = ()> !UnwindSafe for EnvBuilder<'f, Fm, Rm>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more