cel_cxx/env/
mod.rs

1use crate::function::{Arguments, FunctionDecl, FunctionRegistry, IntoFunction};
2use crate::variable::VariableRegistry;
3use crate::{FnMarker, FnMarkerAggr, IntoConstant, RuntimeMarker};
4use std::sync::Arc;
5
6mod inner;
7
8use crate::ffi;
9use crate::{Error, Program, TypedValue};
10pub(crate) use inner::EnvInner;
11
12#[cfg(feature = "async")]
13#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
14use crate::marker::Async;
15
16/// CEL expression evaluation environment.
17///
18/// The `Env` struct represents a CEL environment that can compile expressions
19/// into programs. It encapsulates function registries, variable declarations,
20/// and type information needed for expression compilation.
21///
22/// # Type Parameters
23///
24/// - `'f`: Lifetime of functions registered in this environment
25/// - `Fm`: Function marker type indicating sync/async function support
26/// - `Rm`: Runtime marker type indicating the async runtime (if any)
27///
28/// # Examples
29///
30/// ## Basic Usage
31///
32/// ```rust,no_run
33/// use cel_cxx::*;
34///
35/// let env = Env::builder()
36///     .declare_variable::<String>("name")?
37///     .build()?;
38///     
39/// let program = env.compile("'Hello, ' + name")?;
40/// # Ok::<(), cel_cxx::Error>(())
41/// ```
42///
43/// ## With Custom Functions
44///
45/// ```rust,no_run
46/// use cel_cxx::*;
47///
48/// let env = Env::builder()
49///     .register_global_function("add", |x: i64, y: i64| -> i64 { x + y })?
50///     .build()?;
51///     
52/// let program = env.compile("add(10, 20)")?;
53/// # Ok::<(), cel_cxx::Error>(())
54/// ```
55pub struct Env<'f, Fm: FnMarker = (), Rm: RuntimeMarker = ()> {
56    pub(crate) inner: Arc<EnvInner<'f>>,
57    _fn_marker: std::marker::PhantomData<Fm>,
58    _rt_marker: std::marker::PhantomData<Rm>,
59}
60
61/// Type alias for asynchronous CEL environments.
62///
63/// This is a convenience type alias for environments that support asynchronous
64/// function evaluation.
65#[cfg(feature = "async")]
66#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
67pub type AsyncEnv<'f, Rm = ()> = Env<'f, Async, Rm>;
68
69impl<'f> Env<'f> {
70    /// Creates a new environment builder.
71    ///
72    /// This is the starting point for creating a CEL environment. The builder
73    /// allows you to register functions, declare variables, and configure
74    /// the environment before building it.
75    ///
76    /// # Examples
77    ///
78    /// ```rust,no_run
79    /// use cel_cxx::*;
80    ///
81    /// let builder = Env::builder();
82    /// ```
83    pub fn builder() -> EnvBuilder<'f, ()> {
84        EnvBuilder::<(), ()>::new()
85    }
86}
87
88impl<'f, Fm: FnMarker, Rm: RuntimeMarker> Env<'f, Fm, Rm> {
89    /// Compiles a CEL expression into a Program.
90    ///
91    /// This method takes a CEL expression as a string or byte slice and compiles
92    /// it into a [`Program`] that can be evaluated with different activations.
93    ///
94    /// # Arguments
95    ///
96    /// * `source` - The CEL expression to compile
97    ///
98    /// # Returns
99    ///
100    /// Returns a [`Result`] containing the compiled [`Program`] or an [`Error`]
101    /// if compilation fails.
102    ///
103    /// # Examples
104    ///
105    /// ```rust,no_run
106    /// use cel_cxx::*;
107    ///
108    /// let env = Env::builder().build().unwrap();
109    /// let program = env.compile("1 + 2 * 3").unwrap();
110    /// ```
111    ///
112    /// # Errors
113    ///
114    /// Returns an error if:
115    /// - The expression contains syntax errors
116    /// - Referenced functions or variables are not declared
117    /// - Type checking fails
118    pub fn compile<S: AsRef<[u8]>>(&self, source: S) -> Result<Program<'f, Fm, Rm>, Error> {
119        self.inner.clone().compile::<Fm, Rm, _>(source)
120    }
121}
122
123/// Builder for creating CEL environments.
124///
125/// The `EnvBuilder` allows you to configure a CEL environment by registering
126/// functions, declaring variables, and setting up runtime options before
127/// building the final environment.
128///
129/// # Type Parameters
130///
131/// - `'f`: Lifetime of functions that will be registered
132/// - `Fm`: Function marker type indicating sync/async function support
133/// - `Rm`: Runtime marker type indicating the async runtime (if any)
134///
135/// # Examples
136///
137/// ```rust,no_run
138/// use cel_cxx::*;
139///
140/// let env = Env::builder()
141///     .register_global_function("double", |x: i64| -> i64 { x * 2 })?
142///     .declare_variable::<String>("message")?
143///     .build()?;
144/// # Ok::<(), cel_cxx::Error>(())
145/// ```
146pub struct EnvBuilder<'f, Fm: FnMarker = (), Rm: RuntimeMarker = ()> {
147    function_registry: FunctionRegistry<'f>,
148    variable_registry: VariableRegistry,
149    _fn_marker: std::marker::PhantomData<Fm>,
150    _rt_marker: std::marker::PhantomData<Rm>,
151}
152
153impl<'f, Fm: FnMarker, Rm: RuntimeMarker> EnvBuilder<'f, Fm, Rm> {
154    /// Creates a new environment builder.
155    ///
156    /// # Examples
157    ///
158    /// ```rust,no_run
159    /// use cel_cxx::*;
160    ///
161    /// let builder = EnvBuilder::<()>::new();
162    /// ```
163    pub fn new() -> Self {
164        EnvBuilder {
165            function_registry: FunctionRegistry::new(),
166            variable_registry: VariableRegistry::new(),
167            _fn_marker: std::marker::PhantomData,
168            _rt_marker: std::marker::PhantomData,
169        }
170    }
171}
172
173impl<'f, Fm: FnMarker, Rm: RuntimeMarker> EnvBuilder<'f, Fm, Rm> {
174    /// Registers a function (either global or member).
175    ///
176    /// This method allows you to register custom functions that can be called
177    /// from CEL expressions. The function can be either a global function or
178    /// a member function of a type.
179    ///
180    /// # Function Registration Process
181    ///
182    /// When you register a function, the system:
183    /// 1. Extracts type information from the function signature
184    /// 2. Creates type-safe conversion wrappers
185    /// 3. Stores both the type signature and implementation
186    /// 4. Updates the function marker type to track sync/async status
187    ///
188    /// # Zero-Annotation Benefits
189    ///
190    /// Functions are registered without explicit type annotations:
191    /// - Argument types are automatically inferred
192    /// - Return types are automatically determined
193    /// - Error handling is automatically supported for `Result<T, E>` returns
194    /// - Reference parameters like `&str` are handled safely
195    ///
196    /// # Arguments
197    ///
198    /// * `name` - The name of the function as it will appear in CEL expressions
199    /// * `member` - Whether this is a member function (`true`) or global function (`false`)
200    /// * `f` - The function implementation (function pointer, closure, etc.)
201    ///
202    /// # Type Parameters
203    ///
204    /// * `F` - The function implementation type
205    /// * `Ffm` - The function marker type (sync/async) inferred from the function
206    /// * `Args` - The argument tuple type (automatically inferred)
207    ///
208    /// # Returns
209    ///
210    /// A new `EnvBuilder` with updated function marker type. If this is the first
211    /// async function registered, the marker changes from `()` to `Async`.
212    ///
213    /// # Member vs Global Functions
214    ///
215    /// ## Global Functions
216    /// Called as `function_name(args...)`:
217    /// ```text
218    /// max(a, b)           // max function with two arguments
219    /// calculate(x, y, z)  // calculate function with three arguments
220    /// ```
221    ///
222    /// ## Member Functions  
223    /// Called as `object.method(args...)`:
224    /// ```text
225    /// text.contains(substring)    // contains method on string
226    /// list.size()                // size method on list
227    /// ```
228    ///
229    /// # Function Signature Support
230    ///
231    /// Supports various function signatures:
232    /// - **Simple functions**: `fn(T) -> U`
233    /// - **Functions with errors**: `fn(T) -> Result<U, E>`
234    /// - **Reference parameters**: `fn(&str, i64) -> String`
235    /// - **Multiple parameters**: Up to 10 parameters supported
236    /// - **Closures**: Move closures that capture environment
237    ///
238    /// # Errors
239    ///
240    /// Returns [`Error`] if:
241    /// - Function name conflicts with existing registration
242    /// - Function signature is invalid or unsupported
243    /// - Type inference fails
244    ///
245    /// # Examples
246    ///
247    /// ## Basic Functions
248    ///
249    /// ```rust
250    /// use cel_cxx::*;
251    ///
252    /// let builder = Env::builder()
253    ///     .register_function("add", false, |a: i64, b: i64| a + b)?
254    ///     .register_function("greet", false, |name: &str| format!("Hello, {}!", name))?;
255    /// # Ok::<(), cel_cxx::Error>(())
256    /// ```
257    ///
258    /// ## Member Functions
259    ///
260    /// ```rust
261    /// use cel_cxx::*;
262    ///
263    /// let builder = Env::builder()
264    ///     .register_function("contains", true, |text: &str, substr: &str| text.contains(substr))?
265    ///     .register_function("length", true, |text: &str| text.len() as i64)?;
266    ///
267    /// // Usage in expressions:
268    /// // text.contains("hello")
269    /// // text.length()
270    /// # Ok::<(), cel_cxx::Error>(())
271    /// ```
272    ///
273    /// ## Functions with Error Handling
274    ///
275    /// ```rust
276    /// use cel_cxx::*;
277    ///
278    /// let builder = Env::builder()
279    ///     .register_function("divide", false, |a: f64, b: f64| -> Result<f64, Error> {
280    ///         if b == 0.0 {
281    ///             Err(Error::invalid_argument("division by zero"))
282    ///         } else {
283    ///             Ok(a / b)
284    ///         }
285    ///     })?;
286    /// # Ok::<(), cel_cxx::Error>(())
287    /// ```
288    ///
289    /// ## Closures with Captured Data
290    ///
291    /// ```rust
292    /// use cel_cxx::*;
293    ///
294    /// let multiplier = 5;
295    /// let threshold = 100.0;
296    ///
297    /// let builder = Env::builder()
298    ///     .register_function("scale", false, move |x: i64| x * multiplier)?
299    ///     .register_function("check_limit", false, move |value: f64| value < threshold)?;
300    /// # Ok::<(), cel_cxx::Error>(())
301    /// ```
302    pub fn register_function<F, Ffm, Args>(
303        mut self,
304        name: impl Into<String>,
305        member: bool,
306        f: F,
307    ) -> Result<EnvBuilder<'f, <Ffm as FnMarkerAggr<Fm>>::Output, Rm>, Error>
308    where
309        F: IntoFunction<'f, Ffm, Args>,
310        Ffm: FnMarker + FnMarkerAggr<Fm>,
311        Args: Arguments,
312    {
313        self.function_registry.register(name, member, f)?;
314
315        Ok(EnvBuilder {
316            function_registry: self.function_registry,
317            variable_registry: self.variable_registry,
318            _fn_marker: std::marker::PhantomData,
319            _rt_marker: std::marker::PhantomData,
320        })
321    }
322
323    /// Registers a member function.
324    ///
325    /// This is a convenience method for registering member functions, equivalent to
326    /// calling `register_function(name, true, f)`. Member functions are called using
327    /// dot notation in CEL expressions: `object.method(args...)`.
328    ///
329    /// # Arguments
330    ///
331    /// * `name` - The method name as it will appear in CEL expressions
332    /// * `f` - The function implementation
333    ///
334    /// # Member Function Semantics
335    ///
336    /// Member functions in CEL follow these patterns:
337    /// - First parameter is the "receiver" (the object before the dot)
338    /// - Additional parameters become method arguments
339    /// - Called as `receiver.method(arg1, arg2, ...)`
340    ///
341    /// # Examples
342    ///
343    /// ## String Methods
344    ///
345    /// ```rust
346    /// use cel_cxx::*;
347    ///
348    /// let builder = Env::builder()
349    ///     .register_member_function("upper", |s: &str| s.to_uppercase())?
350    ///     .register_member_function("contains", |s: &str, substr: &str| s.contains(substr))?
351    ///     .register_member_function("repeat", |s: &str, n: i64| s.repeat(n as usize))?;
352    ///
353    /// // Usage in expressions:
354    /// // "hello".upper()           -> "HELLO"
355    /// // "hello world".contains("world") -> true
356    /// // "abc".repeat(3)           -> "abcabcabc"
357    /// # Ok::<(), cel_cxx::Error>(())
358    /// ```
359    ///
360    /// ## Numeric Methods
361    ///
362    /// ```rust
363    /// use cel_cxx::*;
364    ///
365    /// let builder = Env::builder()
366    ///     .register_member_function("abs", |x: f64| x.abs())?
367    ///     .register_member_function("pow", |x: f64, exp: f64| x.powf(exp))?;
368    ///
369    /// // Usage in expressions:
370    /// // (-5.5).abs()     -> 5.5
371    /// // (2.0).pow(3.0)   -> 8.0
372    /// # Ok::<(), cel_cxx::Error>(())
373    /// ```
374    pub fn register_member_function<F, Ffm, Args>(
375        mut self,
376        name: impl Into<String>,
377        f: F,
378    ) -> Result<EnvBuilder<'f, <Ffm as FnMarkerAggr<Fm>>::Output, Rm>, Error>
379    where
380        F: IntoFunction<'f, Ffm, Args>,
381        Ffm: FnMarker + FnMarkerAggr<Fm>,
382        Args: Arguments,
383    {
384        self.function_registry.register_member(name, f)?;
385
386        Ok(EnvBuilder {
387            function_registry: self.function_registry,
388            variable_registry: self.variable_registry,
389            _fn_marker: std::marker::PhantomData,
390            _rt_marker: std::marker::PhantomData,
391        })
392    }
393
394    /// Registers a global function.
395    ///
396    /// This is a convenience method for registering global functions, equivalent to
397    /// calling `register_function(name, false, f)`. Global functions are called directly
398    /// by name in CEL expressions: `function_name(args...)`.
399    ///
400    /// # Arguments
401    ///
402    /// * `name` - The function name as it will appear in CEL expressions
403    /// * `f` - The function implementation
404    ///
405    /// # Global Function Characteristics
406    ///
407    /// Global functions:
408    /// - Are called directly by name without a receiver object
409    /// - Can have 0 to 10 parameters
410    /// - Support all CEL-compatible parameter and return types
411    /// - Can capture environment variables (for closures)
412    ///
413    /// # Function Naming Guidelines
414    ///
415    /// - Use clear, descriptive names: `calculate_tax`, `format_date`
416    /// - Follow CEL naming conventions (snake_case is recommended)
417    /// - Avoid conflicts with built-in CEL functions
418    /// - Consider namespacing for domain-specific functions: `math_sqrt`, `string_trim`
419    ///
420    /// # Examples
421    ///
422    /// ## Mathematical Functions
423    ///
424    /// ```rust
425    /// use cel_cxx::*;
426    ///
427    /// let builder = Env::builder()
428    ///     .register_global_function("add", |a: i64, b: i64| a + b)?
429    ///     .register_global_function("multiply", |a: f64, b: f64| a * b)?
430    ///     .register_global_function("max", |a: i64, b: i64| if a > b { a } else { b })?;
431    ///
432    /// // Usage in expressions:
433    /// // add(10, 20)          -> 30
434    /// // multiply(2.5, 4.0)   -> 10.0
435    /// // max(15, 8)           -> 15
436    /// # Ok::<(), cel_cxx::Error>(())
437    /// ```
438    ///
439    /// ## String Processing Functions
440    ///
441    /// ```rust
442    /// use cel_cxx::*;
443    ///
444    /// let builder = Env::builder()
445    ///     .register_global_function("concat", |a: &str, b: &str| format!("{}{}", a, b))?
446    ///     .register_global_function("trim_prefix", |s: &str, prefix: &str| {
447    ///         s.strip_prefix(prefix).unwrap_or(s).to_string()
448    ///     })?;
449    ///
450    /// // Usage in expressions:
451    /// // concat("Hello, ", "World!")     -> "Hello, World!"
452    /// // trim_prefix("prefixed_text", "prefixed_")  -> "text"
453    /// # Ok::<(), cel_cxx::Error>(())
454    /// ```
455    ///
456    /// ## Business Logic Functions
457    ///
458    /// ```rust
459    /// use cel_cxx::*;
460    ///
461    /// let builder = Env::builder()
462    ///     .register_global_function("calculate_discount", |price: f64, rate: f64| {
463    ///         price * (1.0 - rate.min(1.0).max(0.0))
464    ///     })?
465    ///     .register_global_function("is_valid_email", |email: &str| {
466    ///         email.contains('@') && email.contains('.')
467    ///     })?;
468    ///
469    /// // Usage in expressions:
470    /// // calculate_discount(100.0, 0.15)     -> 85.0
471    /// // is_valid_email("user@domain.com")   -> true
472    /// # Ok::<(), cel_cxx::Error>(())
473    /// ```
474    ///
475    /// ## Functions with Complex Logic
476    ///
477    /// ```rust
478    /// use cel_cxx::*;
479    /// use std::collections::HashMap;
480    ///
481    /// // Function that processes collections
482    /// let builder = Env::builder()
483    ///     .register_global_function("sum_positive", |numbers: Vec<i64>| {
484    ///         numbers.iter().filter(|&x| *x > 0).sum::<i64>()
485    ///     })?;
486    ///
487    /// // Usage in expressions:
488    /// // sum_positive([1, -2, 3, -4, 5])  -> 9
489    /// # Ok::<(), cel_cxx::Error>(())
490    /// ```
491    pub fn register_global_function<F, Ffm, Args>(
492        mut self,
493        name: impl Into<String>,
494        f: F,
495    ) -> Result<EnvBuilder<'f, <Ffm as FnMarkerAggr<Fm>>::Output, Rm>, Error>
496    where
497        F: IntoFunction<'f, Ffm, Args>,
498        Ffm: FnMarker + FnMarkerAggr<Fm>,
499        Args: Arguments,
500    {
501        self.function_registry.register_global(name, f)?;
502
503        Ok(EnvBuilder {
504            function_registry: self.function_registry,
505            variable_registry: self.variable_registry,
506            _fn_marker: std::marker::PhantomData,
507            _rt_marker: std::marker::PhantomData,
508        })
509    }
510
511    /// Declares a function signature without providing an implementation.
512    ///
513    /// This is useful when you want to declare that a function exists for
514    /// type checking purposes, but will provide the implementation later
515    /// via activation bindings.
516    ///
517    /// # Arguments
518    ///
519    /// * `name` - The name of the function
520    /// * `member` - Whether this is a member function (`true`) or global function (`false`)
521    ///
522    /// # Type Parameters
523    ///
524    /// * `D` - The function declaration type that specifies the signature
525    pub fn declare_function<D>(
526        mut self,
527        name: impl Into<String>,
528        member: bool,
529    ) -> Result<Self, Error>
530    where
531        D: FunctionDecl,
532    {
533        self.function_registry.declare::<D>(name, member)?;
534        Ok(EnvBuilder {
535            function_registry: self.function_registry,
536            variable_registry: self.variable_registry,
537            _fn_marker: std::marker::PhantomData,
538            _rt_marker: std::marker::PhantomData,
539        })
540    }
541
542    /// Declares a member function signature without providing an implementation.
543    ///
544    /// # Arguments
545    ///
546    /// * `name` - The name of the member function
547    ///
548    /// # Type Parameters
549    ///
550    /// * `D` - The function declaration type that specifies the signature
551    pub fn declare_member_function<D>(mut self, name: impl Into<String>) -> Result<Self, Error>
552    where
553        D: FunctionDecl,
554    {
555        self.function_registry.declare_member::<D>(name)?;
556        Ok(EnvBuilder {
557            function_registry: self.function_registry,
558            variable_registry: self.variable_registry,
559            _fn_marker: std::marker::PhantomData,
560            _rt_marker: std::marker::PhantomData,
561        })
562    }
563
564    /// Declares a global function signature without providing an implementation.
565    ///
566    /// # Arguments
567    ///
568    /// * `name` - The name of the global function
569    ///
570    /// # Type Parameters
571    ///
572    /// * `D` - The function declaration type that specifies the signature
573    pub fn declare_global_function<D>(mut self, name: impl Into<String>) -> Result<Self, Error>
574    where
575        D: FunctionDecl,
576    {
577        self.function_registry.declare_global::<D>(name)?;
578        Ok(EnvBuilder {
579            function_registry: self.function_registry,
580            variable_registry: self.variable_registry,
581            _fn_marker: std::marker::PhantomData,
582            _rt_marker: std::marker::PhantomData,
583        })
584    }
585
586    /// Defines a constant value that can be referenced in expressions.
587    ///
588    /// Constants are immutable values that are resolved at compile time.
589    ///
590    /// # Arguments
591    ///
592    /// * `name` - The name of the constant
593    /// * `value` - The constant value
594    ///
595    /// # Examples
596    ///
597    /// ```rust,no_run
598    /// use cel_cxx::*;
599    ///
600    /// let builder = Env::builder()
601    ///     .define_constant("PI", 3.14159)
602    ///     .unwrap();
603    /// # Ok::<(), cel_cxx::Error>(())
604    /// ```
605    pub fn define_constant<T>(mut self, name: impl Into<String>, value: T) -> Result<Self, Error>
606    where
607        T: IntoConstant,
608    {
609        self.variable_registry.define_constant(name, value)?;
610        Ok(EnvBuilder {
611            function_registry: self.function_registry,
612            variable_registry: self.variable_registry,
613            _fn_marker: std::marker::PhantomData,
614            _rt_marker: std::marker::PhantomData,
615        })
616    }
617
618    /// Declares a variable of a specific type.
619    ///
620    /// This declares that a variable of the given name and type may be
621    /// provided during evaluation. The actual value must be bound in
622    /// the activation when evaluating expressions.
623    ///
624    /// # Arguments
625    ///
626    /// * `name` - The name of the variable
627    ///
628    /// # Type Parameters
629    ///
630    /// * `T` - The type of the variable
631    ///
632    /// # Examples
633    ///
634    /// ```rust,no_run
635    /// use cel_cxx::*;
636    ///
637    /// let builder = Env::builder()
638    ///     .declare_variable::<String>("user_name")?
639    ///     .declare_variable::<i64>("age")?;
640    ///
641    /// # Ok::<(), cel_cxx::Error>(())
642    /// ```
643    pub fn declare_variable<T>(mut self, name: impl Into<String>) -> Result<Self, Error>
644    where
645        T: TypedValue,
646    {
647        self.variable_registry.declare::<T>(name)?;
648        Ok(EnvBuilder {
649            function_registry: self.function_registry,
650            variable_registry: self.variable_registry,
651            _fn_marker: std::marker::PhantomData,
652            _rt_marker: std::marker::PhantomData,
653        })
654    }
655
656    /// Builds the environment from the configured builder.
657    ///
658    /// This method consumes the builder and creates the final [`Env`] instance
659    /// that can be used to compile CEL expressions.
660    ///
661    /// # Returns
662    ///
663    /// Returns a [`Result`] containing the built [`Env`] or an [`Error`] if
664    /// the environment could not be created.
665    ///
666    /// # Examples
667    ///
668    /// ```rust,no_run
669    /// use cel_cxx::*;
670    ///
671    /// let env = Env::builder()
672    ///     .declare_variable::<String>("name")?
673    ///     .build()?;
674    /// # Ok::<(), cel_cxx::Error>(())
675    /// ```
676    ///
677    /// # Errors
678    ///
679    /// Returns an error if the environment configuration is invalid or
680    /// if the underlying CEL environment cannot be created.
681    pub fn build(self) -> Result<Env<'f, Fm, Rm>, Error> {
682        let inner = EnvInner::new_with_registries(self.function_registry, self.variable_registry)
683            .map_err(|ffi_status| ffi::error_to_rust(&ffi_status))?;
684        let env = Env {
685            inner: Arc::new(inner),
686            _fn_marker: self._fn_marker,
687            _rt_marker: self._rt_marker,
688        };
689        Ok(env)
690    }
691}
692
693#[cfg(feature = "async")]
694#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
695const _: () = {
696    use crate::r#async::*;
697
698    impl<'f, Rm: RuntimeMarker> Env<'f, (), Rm> {
699        /// Forces conversion to an async environment.
700        ///
701        /// This method converts a synchronous environment to an asynchronous one,
702        /// allowing it to work with async functions and evaluation.
703        ///
704        /// # Type Parameters
705        ///
706        /// * `Rt` - The async runtime type to use
707        ///
708        /// # Examples
709        ///
710        /// ```rust,no_run
711        /// # #[cfg(feature = "async")]
712        /// # {
713        /// use cel_cxx::*;
714        ///
715        /// let sync_env = Env::builder().build()?;
716        /// let async_env = sync_env.force_async();
717        /// # }
718        /// # Ok::<(), cel_cxx::Error>(())
719        /// ```
720        pub fn force_async(self) -> Env<'f, Async, Rm> {
721            Env {
722                inner: self.inner,
723                _fn_marker: std::marker::PhantomData,
724                _rt_marker: std::marker::PhantomData,
725            }
726        }
727    }
728
729    impl<'f, Rm: RuntimeMarker> EnvBuilder<'f, (), Rm> {
730        /// Forces conversion to an async environment builder.
731        ///
732        /// This method converts a synchronous environment builder to an asynchronous one,
733        /// allowing it to register async functions and build async environments.
734        ///
735        /// # Examples
736        ///
737        /// ```rust,no_run
738        /// # #[cfg(feature = "async")]
739        /// # {
740        /// use cel_cxx::*;
741        ///
742        /// let async_builder = Env::builder().force_async();
743        /// # }
744        /// ```
745        pub fn force_async(self) -> EnvBuilder<'f, Async, Rm> {
746            EnvBuilder {
747                function_registry: self.function_registry,
748                variable_registry: self.variable_registry,
749                _fn_marker: std::marker::PhantomData,
750                _rt_marker: std::marker::PhantomData,
751            }
752        }
753    }
754
755    impl<'f, Fm: FnMarker> Env<'f, Fm, ()> {
756        /// Sets the async runtime for this environment.
757        ///
758        /// This method specifies which async runtime should be used for
759        /// asynchronous evaluation of expressions.
760        ///
761        /// # Type Parameters
762        ///
763        /// * `Rt` - The runtime type to use (must implement [`Runtime`])
764        ///
765        /// # Examples
766        ///
767        /// ```rust,no_run
768        /// # #[cfg(feature = "async")]
769        /// # {
770        /// use cel_cxx::*;
771        ///
772        /// let env = Env::builder()
773        ///     .build()?
774        ///     .use_runtime::<Tokio>();
775        /// # }
776        /// # Ok::<(), cel_cxx::Error>(())
777        /// ```
778        pub fn use_runtime<Rt: Runtime>(self) -> Env<'f, Fm, Rt> {
779            let inner = self.inner.clone();
780            Env {
781                inner,
782                _fn_marker: self._fn_marker,
783                _rt_marker: std::marker::PhantomData,
784            }
785        }
786
787        /// Configures the environment to use the Tokio async runtime.
788        ///
789        /// This is a convenience method for setting the runtime to Tokio.
790        /// Requires the `tokio` feature to be enabled.
791        ///
792        /// # Examples
793        ///
794        /// ```rust,no_run
795        /// # #[cfg(all(feature = "async", feature = "tokio"))]
796        /// # {
797        /// use cel_cxx::*;
798        ///
799        /// let env = Env::builder()
800        ///     .build()?
801        ///     .use_tokio();
802        /// # }
803        /// # Ok::<(), cel_cxx::Error>(())
804        /// ```
805        #[cfg(feature = "tokio")]
806        #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
807        pub fn use_tokio(self) -> Env<'f, Fm, Tokio> {
808            self.use_runtime::<Tokio>()
809        }
810
811        /// Configures the environment to use the async-std runtime.
812        ///
813        /// This is a convenience method for setting the runtime to async-std.
814        /// Requires the `async-std` feature to be enabled.
815        ///
816        /// # Examples
817        ///
818        /// ```rust,no_run
819        /// # #[cfg(all(feature = "async", feature = "async-std"))]
820        /// # {
821        /// use cel_cxx::*;
822        ///
823        /// let env = Env::builder()
824        ///     .build()?
825        ///     .use_async_std();
826        /// # }
827        /// # Ok::<(), cel_cxx::Error>(())
828        /// ```
829        #[cfg(feature = "async-std")]
830        #[cfg_attr(docsrs, doc(cfg(feature = "async-std")))]
831        pub fn use_async_std(self) -> Env<'f, Fm, AsyncStd> {
832            self.use_runtime::<AsyncStd>()
833        }
834    }
835
836    impl<'f, Fm: FnMarker> EnvBuilder<'f, Fm, ()> {
837        /// Sets the async runtime for the environment builder.
838        ///
839        /// This method specifies which async runtime should be used by
840        /// environments built from this builder.
841        ///
842        /// # Type Parameters
843        ///
844        /// * `Rt` - The runtime type to use (must implement [`Runtime`])
845        ///
846        /// # Examples
847        ///
848        /// ```rust,no_run
849        /// # #[cfg(feature = "async")]
850        /// # {
851        /// use cel_cxx::*;
852        ///
853        /// let builder = Env::builder().use_runtime::<Tokio>();
854        /// # }
855        /// ```
856        pub fn use_runtime<Rt: Runtime>(self) -> EnvBuilder<'f, Fm, Rt> {
857            EnvBuilder {
858                function_registry: self.function_registry,
859                variable_registry: self.variable_registry,
860                _fn_marker: self._fn_marker,
861                _rt_marker: std::marker::PhantomData,
862            }
863        }
864
865        /// Configures the builder to use the Tokio async runtime.
866        ///
867        /// This is a convenience method for setting the runtime to Tokio.
868        /// Requires the `tokio` feature to be enabled.
869        ///
870        /// # Examples
871        ///
872        /// ```rust,no_run
873        /// # #[cfg(all(feature = "async", feature = "tokio"))]
874        /// # {
875        /// use cel_cxx::*;
876        ///
877        /// let builder = Env::builder().use_tokio();
878        /// # }
879        /// ```
880        #[cfg(feature = "tokio")]
881        #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
882        pub fn use_tokio(self) -> EnvBuilder<'f, Fm, Tokio> {
883            self.use_runtime::<Tokio>()
884        }
885
886        /// Configures the builder to use the async-std runtime.
887        ///
888        /// This is a convenience method for setting the runtime to async-std.
889        /// Requires the `async-std` feature to be enabled.
890        ///
891        /// # Examples
892        ///
893        /// ```rust,no_run
894        /// # #[cfg(all(feature = "async", feature = "async-std"))]
895        /// # {
896        /// use cel_cxx::*;
897        ///
898        /// let builder = Env::builder().use_async_std();
899        /// # }
900        /// ```
901        #[cfg(feature = "async-std")]
902        #[cfg_attr(docsrs, doc(cfg(feature = "async-std")))]
903        pub fn use_async_std(self) -> EnvBuilder<'f, Fm, AsyncStd> {
904            self.use_runtime::<AsyncStd>()
905        }
906    }
907};
908
909impl<'f, Fm: FnMarker, Rm: RuntimeMarker> std::fmt::Debug for Env<'f, Fm, Rm> {
910    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
911        f.debug_struct("Env").field("inner", &self.inner).finish()
912    }
913}
914
915impl<'f, Fm: FnMarker, Rm: RuntimeMarker> Clone for Env<'f, Fm, Rm> {
916    fn clone(&self) -> Self {
917        Env {
918            inner: self.inner.clone(),
919            _fn_marker: self._fn_marker,
920            _rt_marker: self._rt_marker,
921        }
922    }
923}
924
925impl<'f, Fm: FnMarker, Rm: RuntimeMarker> std::fmt::Debug for EnvBuilder<'f, Fm, Rm> {
926    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
927        f.debug_struct("EnvBuilder")
928            .field("function_registry", &self.function_registry)
929            .field("variable_registry", &self.variable_registry)
930            .finish()
931    }
932}
933
934impl<'f, Fm: FnMarker, Rm: RuntimeMarker> Default for EnvBuilder<'f, Fm, Rm> {
935    fn default() -> Self {
936        EnvBuilder {
937            function_registry: FunctionRegistry::new(),
938            variable_registry: VariableRegistry::new(),
939            _fn_marker: std::marker::PhantomData,
940            _rt_marker: std::marker::PhantomData,
941        }
942    }
943}