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, EnvInnerOptions};
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    options: EnvInnerOptions,
150    _fn_marker: std::marker::PhantomData<Fm>,
151    _rt_marker: std::marker::PhantomData<Rm>,
152}
153
154impl<'f, Fm: FnMarker, Rm: RuntimeMarker> EnvBuilder<'f, Fm, Rm> {
155    /// Creates a new environment builder.
156    ///
157    /// # Examples
158    ///
159    /// ```rust,no_run
160    /// use cel_cxx::*;
161    ///
162    /// let builder = EnvBuilder::<()>::new();
163    /// ```
164    pub fn new() -> Self {
165        EnvBuilder {
166            function_registry: FunctionRegistry::new(),
167            variable_registry: VariableRegistry::new(),
168            options: EnvInnerOptions::default(),
169            _fn_marker: std::marker::PhantomData,
170            _rt_marker: std::marker::PhantomData,
171        }
172    }
173}
174
175impl<'f, Fm: FnMarker, Rm: RuntimeMarker> EnvBuilder<'f, Fm, Rm> {
176    /// Sets the CEL container for the environment, which acts as a namespace for unqualified names.
177    ///
178    /// **Default**: Empty string (root scope)
179    ///
180    /// The container influences how unqualified names (like function or variable names) are
181    /// resolved during expression compilation. This affects the CEL runtime's name resolution
182    /// behavior for types, functions, and variables.
183    ///
184    /// # CEL Syntax Impact
185    ///
186    /// When a container is set, unqualified names in CEL expressions are automatically prefixed
187    /// with the container namespace:
188    ///
189    /// ```cel
190    /// // With container "my.app", this expression:
191    /// MyMessage{field: 123}
192    /// // is equivalent to:
193    /// my.app.MyMessage{field: 123}
194    /// ```
195    ///
196    /// # Examples
197    ///
198    /// ```rust,no_run
199    /// use cel_cxx::*;
200    /// 
201    /// // Set container for protobuf message resolution
202    /// let env = Env::builder()
203    ///     .with_container("com.example.proto")
204    ///     .build()?;
205    /// 
206    /// // Now "UserMessage" resolves to "com.example.proto.UserMessage"
207    /// let program = env.compile("UserMessage{name: 'Alice', id: 123}")?;
208    /// # Ok::<(), cel_cxx::Error>(())
209    /// ```
210    pub fn with_container(mut self, container: impl Into<String>) -> Self {
211        self.options.container = container.into();
212        self
213    }
214
215    /// Enables or disables the CEL standard library of functions and macros.
216    ///
217    /// **Default**: Enabled (`true`)
218    ///
219    /// The standard library provides a rich set of common functions for types like `string`,
220    /// `list`, `map`, as well as logical and arithmetic operators. Disabling it can reduce 
221    /// the environment's footprint if only custom functions are needed.
222    ///
223    /// # CEL Syntax Impact
224    ///
225    /// When enabled, provides access to all standard CEL operations:
226    /// - **Arithmetic**: `+`, `-`, `*`, `/`, `%`
227    /// - **Comparison**: `==`, `!=`, `<`, `<=`, `>`, `>=`
228    /// - **Logical**: `&&`, `||`, `!`
229    /// - **String operations**: `+` (concatenation), `contains()`, `startsWith()`, `endsWith()`, `size()`
230    /// - **List operations**: `size()`, `in`, `[]` (indexing), `+` (concatenation)
231    /// - **Map operations**: `size()`, `in`, `[]` (key access), `+` (merge)
232    /// - **Type conversions**: `int()`, `uint()`, `double()`, `string()`, `bytes()`
233    /// - **Conditional**: `? :` (ternary operator)
234    /// - **Macros**: `has()`, `all()`, `exists()`, `exists_one()`, `map()`, `filter()`
235    ///
236    /// # Examples
237    ///
238    /// ```rust
239    /// use cel_cxx::*;
240    /// 
241    /// // Standard library enabled (default)
242    /// let env = Env::builder()
243    ///     .with_standard(true)
244    ///     .build()?;
245    /// 
246    /// // Can use standard functions
247    /// let program = env.compile("'hello'.size() + ' world'.size() == 11")?;
248    /// let result = program.evaluate(&Activation::new())?;
249    /// assert_eq!(result, Value::Bool(true));
250    /// 
251    /// // Standard library disabled
252    /// let env_minimal = Env::builder()
253    ///     .with_standard(false)
254    ///     .build()?;
255    /// 
256    /// // Standard functions not available - would cause compilation error
257    /// // env_minimal.compile("'hello'.size()")?; // Error!
258    /// # Ok::<(), cel_cxx::Error>(())
259    /// ```
260    pub fn with_standard(mut self, enable: bool) -> Self {
261        self.options.enable_standard = enable;
262        self
263    }
264
265    /// Enables or disables support for CEL's optional types and related syntax.
266    ///
267    /// **Default**: Disabled (`false`)
268    ///
269    /// This enables the `optional` type and related features like optional field selection (`.?`),
270    /// optional index/key access (`[?_]`), and optional value construction (`{?key: ...}`).
271    /// Required for some extensions like regex that return optional values.
272    ///
273    /// # CEL Syntax Impact
274    ///
275    /// When enabled, adds support for:
276    /// - **Optional type**: `optional<T>` for values that may or may not be present
277    /// - **Optional field selection**: `msg.?field` returns `optional<T>` instead of error
278    /// - **Optional indexing**: `list[?index]` and `map[?key]` return `optional<T>`
279    /// - **Optional map construction**: `{?'key': value}` only includes entry if value is present
280    /// - **Optional methods**: `.hasValue()`, `.value()`, `.orValue(default)`
281    /// - **Optional literals**: `optional.of(value)`, `optional.none()`
282    ///
283    /// # Examples
284    ///
285    /// ```rust
286    /// use cel_cxx::*;
287    /// 
288    /// let env = Env::builder()
289    ///     .with_optional(true)
290    ///     .build()?;
291    /// 
292    /// // Optional field selection
293    /// let program = env.compile("msg.?field.orValue('default')")?;
294    /// 
295    /// // Optional map construction
296    /// let program2 = env.compile("{'name': 'bob', ?'age': optional.of(25)}")?;
297    /// 
298    /// // Optional indexing
299    /// let program3 = env.compile("list[?5].hasValue()")?;
300    /// # Ok::<(), cel_cxx::Error>(())
301    /// ```
302    pub fn with_optional(mut self, enable: bool) -> Self {
303        self.options.enable_optional = enable;
304        self
305    }
306
307    /// Enables or disables the Bindings extension.
308    ///
309    /// **Default**: Disabled (`false`)
310    ///
311    /// This extension provides the `cel.bind()` macro, which allows for temporary variable
312    /// bindings within a CEL expression to improve readability and performance by avoiding
313    /// repeated calculations.
314    ///
315    /// # Available Functions
316    ///
317    /// | Function | Description | Example |
318    /// |----------|-------------|---------|
319    /// | `cel.bind(var, init, result)` | Bind variable to initialization expression | `cel.bind(x, 5, x * x)` |
320    ///
321    /// # CEL Syntax Impact
322    ///
323    /// When enabled, adds the `cel.bind()` macro that creates local variable scopes:
324    /// - Variables are scoped to the result expression
325    /// - Supports nested bindings
326    /// - Enables performance optimization through value reuse
327    /// - Improves readability of complex expressions
328    ///
329    /// # Examples
330    ///
331    /// ```rust
332    /// use cel_cxx::*;
333    /// 
334    /// let env = Env::builder()
335    ///     .with_ext_bindings(true)
336    ///     .build()?;
337    /// 
338    /// // Simple binding
339    /// let program = env.compile("cel.bind(x, 5, x * x)")?;
340    /// let result = program.evaluate(&Activation::new())?;
341    /// assert_eq!(result, Value::Int(25));
342    /// 
343    /// // Nested bindings for complex calculations
344    /// let program2 = env.compile(r#"
345    ///     cel.bind(a, 'hello',
346    ///       cel.bind(b, 'world', 
347    ///         a + ' ' + b + '!'))
348    /// "#)?;
349    /// # Ok::<(), cel_cxx::Error>(())
350    /// ```
351    pub fn with_ext_bindings(mut self, enable: bool) -> Self {
352        self.options.enable_ext_bindings = enable;
353        self
354    }
355
356    /// Enables or disables the Encoders extension.
357    ///
358    /// **Default**: Disabled (`false`)
359    ///
360    /// This extension provides functions for encoding and decoding between common data formats,
361    /// such as Base64. All functions handle edge cases gracefully and maintain CEL's safety guarantees.
362    ///
363    /// # Available Functions
364    ///
365    /// | Function | Description | Example |
366    /// |----------|-------------|---------|
367    /// | `base64.encode(bytes)` | Encode bytes to Base64 string | `base64.encode(b'hello')` |
368    /// | `base64.decode(string)` | Decode Base64 string to bytes | `base64.decode('aGVsbG8=')` |
369    ///
370    /// # CEL Syntax Impact
371    ///
372    /// When enabled, adds encoding/decoding functions in the `base64` namespace:
373    /// - Supports both standard and raw (unpadded) Base64 encoding
374    /// - Automatically handles missing padding in decode operations
375    /// - Returns errors for invalid Base64 input
376    ///
377    /// # Examples
378    ///
379    /// ```rust
380    /// use cel_cxx::*;
381    /// 
382    /// let env = Env::builder()
383    ///     .with_ext_encoders(true)
384    ///     .build()?;
385    /// 
386    /// // Encode bytes to Base64
387    /// let program = env.compile("base64.encode(b'hello')")?;
388    /// let result = program.evaluate(&Activation::new())?;
389    /// assert_eq!(result, Value::String("aGVsbG8=".into()));
390    /// 
391    /// // Decode Base64 to bytes
392    /// let program2 = env.compile("base64.decode('aGVsbG8=')")?;
393    /// let result2 = program2.evaluate(&Activation::new())?;
394    /// assert_eq!(result2, Value::Bytes(b"hello".to_vec()));
395    /// # Ok::<(), cel_cxx::Error>(())
396    /// ```
397    pub fn with_ext_encoders(mut self, enable: bool) -> Self {
398        self.options.enable_ext_encoders = enable;
399        self
400    }
401
402    /// Enables or disables the Lists extension.
403    ///
404    /// **Default**: Disabled (`false`)
405    ///
406    /// This extension provides additional functions for working with lists, such as slicing,
407    /// flattening, sorting, and deduplication. All functions maintain CEL's immutability 
408    /// guarantees and return new lists rather than modifying existing ones.
409    ///
410    /// # Available Functions
411    ///
412    /// | Function | Description | Example |
413    /// |----------|-------------|---------|
414    /// | `list.slice(start, end)` | Extract sub-list | `[1,2,3,4].slice(1,3)` → `[2,3]` |
415    /// | `list.flatten()` | Flatten nested lists | `[[1,2],[3,4]].flatten()` → `[1,2,3,4]` |
416    /// | `list.flatten(depth)` | Flatten to specified depth | `[1,[2,[3]]].flatten(1)` → `[1,2,[3]]` |
417    /// | `list.distinct()` | Remove duplicates | `[1,2,2,3].distinct()` → `[1,2,3]` |
418    /// | `list.reverse()` | Reverse list order | `[1,2,3].reverse()` → `[3,2,1]` |
419    /// | `list.sort()` | Sort comparable elements | `[3,1,2].sort()` → `[1,2,3]` |
420    /// | `list.sortBy(var, expr)` | Sort by key expression | `users.sortBy(u, u.age)` |
421    /// | `lists.range(n)` | Generate number sequence | `lists.range(3)` → `[0,1,2]` |
422    /// | `lists.range(start, end)` | Generate range | `lists.range(2,5)` → `[2,3,4]` |
423    ///
424    /// # CEL Syntax Impact
425    ///
426    /// When enabled, adds advanced list manipulation capabilities:
427    /// - Zero-based indexing for all operations
428    /// - Type safety for sort operations (comparable types only)
429    /// - Efficient deduplication and flattening algorithms
430    /// - Lazy evaluation for range generation
431    ///
432    /// # Examples
433    ///
434    /// ```rust
435    /// use cel_cxx::*;
436    /// 
437    /// let env = Env::builder()
438    ///     .with_ext_lists(true)
439    ///     .build()?;
440    /// 
441    /// // List slicing
442    /// let program = env.compile("[1, 2, 3, 4].slice(1, 3)")?;
443    /// let result = program.evaluate(&Activation::new())?;
444    /// assert_eq!(result, Value::List(vec![Value::Int(2), Value::Int(3)]));
445    /// 
446    /// // List sorting
447    /// let program2 = env.compile("[3, 1, 2].sort()")?;
448    /// let result2 = program2.evaluate(&Activation::new())?;
449    /// assert_eq!(result2, Value::List(vec![Value::Int(1), Value::Int(2), Value::Int(3)]));
450    /// 
451    /// // Generate ranges
452    /// let program3 = env.compile("lists.range(3)")?;
453    /// let result3 = program3.evaluate(&Activation::new())?;
454    /// assert_eq!(result3, Value::List(vec![Value::Int(0), Value::Int(1), Value::Int(2)]));
455    /// # Ok::<(), cel_cxx::Error>(())
456    /// ```
457    pub fn with_ext_lists(mut self, enable: bool) -> Self {
458        self.options.enable_ext_lists = enable;
459        self
460    }
461
462    /// Enables or disables the Math extension.
463    ///
464    /// **Default**: Disabled (`false`)
465    ///
466    /// This extension provides advanced mathematical functions beyond the standard operators,
467    /// including min/max operations, rounding functions, absolute value, sign detection,
468    /// bitwise operations, floating point helpers, and square root. All functions are 
469    /// deterministic and side-effect free.
470    ///
471    /// **Note**: All macros use the 'math' namespace; however, at the time of macro
472    /// expansion the namespace looks just like any other identifier. If you are
473    /// currently using a variable named 'math', the macro will likely work just as
474    /// intended; however, there is some chance for collision.
475    ///
476    /// # Available Functions
477    ///
478         /// ## Min/Max Operations
479     /// | Function | Description | Example |
480     /// |----------|-------------|---------|
481     /// | `math.greatest(...)` | Greatest value from arguments/list | `math.greatest(1,2,3)` → `3` |
482     /// | `math.least(...)` | Least value from arguments/list | `math.least([1,2,3])` → `1` |
483    ///
484    /// ## Absolute Value and Sign
485    /// | Function | Description | Example |
486    /// |----------|-------------|---------|
487    /// | `math.abs(number)` | Absolute value | `math.abs(-5)` → `5` |
488    /// | `math.sign(number)` | Sign (-1, 0, or 1) | `math.sign(-5)` → `-1` |
489    ///
490    /// ## Rounding Functions
491    /// | Function | Description | Example |
492    /// |----------|-------------|---------|
493    /// | `math.ceil(number)` | Round up | `math.ceil(3.14)` → `4.0` |
494    /// | `math.floor(number)` | Round down | `math.floor(3.14)` → `3.0` |
495    /// | `math.round(number)` | Round to nearest | `math.round(3.14)` → `3.0` |
496    /// | `math.trunc(number)` | Truncate decimals | `math.trunc(3.14)` → `3.0` |
497    ///
498    /// ## Bitwise Operations
499    /// | Function | Description | Example |
500    /// |----------|-------------|---------|
501    /// | `math.bitAnd(a,b)` | Bitwise AND | `math.bitAnd(5,3)` → `1` |
502    /// | `math.bitOr(a,b)` | Bitwise OR | `math.bitOr(5,3)` → `7` |
503    /// | `math.bitXor(a,b)` | Bitwise XOR | `math.bitXor(5,3)` → `6` |
504    /// | `math.bitNot(n)` | Bitwise NOT | `math.bitNot(5)` → `-6` |
505    /// | `math.bitShiftLeft(n,bits)` | Left bit shift | `math.bitShiftLeft(5,1)` → `10` |
506    /// | `math.bitShiftRight(n,bits)` | Right bit shift | `math.bitShiftRight(5,1)` → `2` |
507    ///
508    /// ## Floating Point Helpers
509    /// | Function | Description | Example |
510    /// |----------|-------------|---------|
511    /// | `math.isInf(number)` | Check if infinite | `math.isInf(1.0/0.0)` → `true` |
512    /// | `math.isNaN(number)` | Check if NaN | `math.isNaN(0.0/0.0)` → `true` |
513    /// | `math.isFinite(number)` | Check if finite | `math.isFinite(1.2)` → `true` |
514    ///
515    /// ## Square Root
516    /// | Function | Description | Example |
517    /// |----------|-------------|---------|
518    /// | `math.sqrt(number)` | Square root | `math.sqrt(81)` → `9.0` |
519    ///
520    /// # CEL Syntax Impact
521    ///
522    /// When enabled, adds mathematical functions in the `math` namespace:
523    /// - Supports both integer and floating-point operations
524    /// - Bitwise operations work on integer types only
525    /// - Rounding functions return double type
526    /// - Min/max functions preserve input type
527    /// - Floating point helpers work with double type
528    /// - Square root always returns double type
529    ///
530    /// # Examples
531    ///
532    /// ```rust
533    /// use cel_cxx::*;
534    /// 
535    /// let env = Env::builder()
536    ///     .with_ext_math(true)
537    ///     .build()?;
538    /// 
539    /// // Greatest/least operations (macros)
540    /// let program = env.compile("math.greatest(5, 2, 8, 1)")?;
541    /// let result = program.evaluate(&Activation::new())?;
542    /// assert_eq!(result, Value::Int(8));
543    /// 
544    /// let program2 = env.compile("math.least([-42.0, -21.5, -100.0])")?;
545    /// let result2 = program2.evaluate(&Activation::new())?;
546    /// assert_eq!(result2, Value::Double(-100.0));
547    /// 
548         /// // Absolute value
549     /// let program3 = env.compile("math.abs(-5)")?;
550     /// let result3 = program3.evaluate(&Activation::new())?;
551     /// assert_eq!(result3, Value::Int(5));
552    /// 
553    /// // Rounding functions
554    /// let program4 = env.compile("math.ceil(3.14)")?;
555    /// let result4 = program4.evaluate(&Activation::new())?;
556    /// assert_eq!(result4, Value::Double(4.0));
557    /// 
558    /// // Bitwise operations
559    /// let program5 = env.compile("math.bitAnd(5, 3)")?;
560    /// let result5 = program5.evaluate(&Activation::new())?;
561    /// assert_eq!(result5, Value::Int(1));
562    /// 
563    /// // Floating point helpers
564    /// let program6 = env.compile("math.isFinite(1.2)")?;
565    /// let result6 = program6.evaluate(&Activation::new())?;
566    /// assert_eq!(result6, Value::Bool(true));
567    /// 
568    /// // Square root
569    /// let program7 = env.compile("math.sqrt(81)")?;
570    /// let result7 = program7.evaluate(&Activation::new())?;
571    /// assert_eq!(result7, Value::Double(9.0));
572    /// # Ok::<(), cel_cxx::Error>(())
573    /// ```
574    pub fn with_ext_math(mut self, enable: bool) -> Self {
575        self.options.enable_ext_math = enable;
576        self
577    }
578
579    /// Enables or disables the Protocol Buffers (Protobuf) extension.
580    ///
581    /// **Default**: Disabled (`false`)
582    ///
583    /// This provides enhanced support for working with Protocol Buffer messages, particularly
584    /// for accessing and testing proto2 extension fields. Requires proper setup of Protobuf 
585    /// descriptors in the environment.
586    ///
587    /// # Available Functions
588    ///
589    /// | Function | Description | Example |
590    /// |----------|-------------|---------|
591    /// | `proto.getExt(msg, ext)` | Get extension field value | `proto.getExt(msg, my.extension)` |
592    /// | `proto.hasExt(msg, ext)` | Test extension field presence | `proto.hasExt(msg, my.extension)` |
593    ///
594    /// # CEL Syntax Impact
595    ///
596    /// When enabled, adds proto2 extension support:
597    /// - `proto.getExt()` returns extension value or default if not set
598    /// - `proto.hasExt()` returns boolean indicating if extension is explicitly set
599    /// - Extension names must be fully qualified (e.g., `com.example.my_extension`)
600    /// - Uses safe-traversal semantics (no errors on missing fields)
601    /// - Only works with proto2 syntax messages that support extensions
602    ///
603    /// # Examples
604    ///
605    /// ```rust,no_run
606    /// use cel_cxx::*;
607    /// 
608    /// let env = Env::builder()
609    ///     .with_ext_proto(true)
610    ///     .build()?;
611    /// 
612    /// // Access extension field
613    /// let program = env.compile("proto.getExt(my_message, com.example.priority_ext)")?;
614    /// 
615    /// // Test extension presence
616    /// let program2 = env.compile("proto.hasExt(my_message, com.example.priority_ext)")?;
617    /// 
618    /// // Conditional processing based on extensions
619    /// let program3 = env.compile(r#"
620    ///     proto.hasExt(msg, com.example.metadata_ext) ? 
621    ///         proto.getExt(msg, com.example.metadata_ext).value : 
622    ///         "default"
623    /// "#)?;
624    /// # Ok::<(), cel_cxx::Error>(())
625    /// ```
626    pub fn with_ext_proto(mut self, enable: bool) -> Self {
627        self.options.enable_ext_proto = enable;
628        self
629    }
630
631    /// Enables or disables the Regular Expression (Regex) extension.
632    ///
633    /// **Default**: Disabled (`false`)
634    ///
635    /// This extension provides functions for pattern matching on strings using regular expressions,
636    /// including pattern extraction, replacement, and text processing. Requires optional types
637    /// to be enabled for proper operation.
638    ///
639    /// # Available Functions
640    ///
641    /// | Function | Description | Example |
642    /// |----------|-------------|---------|
643    /// | `regex.extract(text, pattern)` | Extract first match (optional) | `regex.extract('hello', 'h(.*)o')` → `optional('ell')` |
644    /// | `regex.extractAll(text, pattern)` | Extract all matches | `regex.extractAll('a1 b2', '\\d+')` → `['1', '2']` |
645    /// | `regex.replace(text, pattern, replacement)` | Replace all matches | `regex.replace('hello', 'l', 'x')` → `'hexxo'` |
646    /// | `regex.replace(text, pattern, replacement, count)` | Replace up to count | `regex.replace('hello', 'l', 'x', 1)` → `'hexlo'` |
647    ///
648    /// # CEL Syntax Impact
649    ///
650    /// When enabled, adds regex functions in the `regex` namespace:
651    /// - `regex.extract()` returns `optional<string>` (requires optional types)
652    /// - Supports 0 or 1 capture groups only (error for multiple groups)
653    /// - Uses standard regex syntax with proper escaping
654    /// - Replacement supports capture group references (`\1`, `\2`, etc.)
655    /// - Count parameter in replace: 0=no replacement, negative=replace all
656    ///
657    /// # Examples
658    ///
659    /// ```rust
660    /// use cel_cxx::*;
661    /// 
662    /// let env = Env::builder()
663    ///     .with_ext_regex(true)
664    ///     .with_optional(true)  // Required for regex.extract
665    ///     .build()?;
666    /// 
667    /// // Pattern extraction
668    /// let program = env.compile(r#"regex.extract('hello world', 'hello (.*)')"#)?;
669    /// 
670    /// // Extract all matches
671    /// let program2 = env.compile(r#"regex.extractAll('id:123, id:456', 'id:(\\d+)')"#)?;
672    /// 
673    /// // Pattern replacement with capture groups
674    /// let program3 = env.compile(r#"regex.replace('John Doe', '(\\w+) (\\w+)', r'\2, \1')"#)?;
675    /// # Ok::<(), cel_cxx::Error>(())
676    /// ```
677    pub fn with_ext_regex(mut self, enable: bool) -> Self {
678        self.options.enable_ext_regex = enable;
679        self
680    }
681
682    /// Enables or disables the Regular Expression (RE) extension.
683    ///
684    /// **Default**: Disabled (`false`)
685    ///
686    /// This extension provides C++ specific regular expression functions built on the RE2 library,
687    /// offering additional pattern matching capabilities with different semantics than the standard
688    /// regex extension. This is specific to the C++ CEL implementation.
689    ///
690    /// # Available Functions
691    ///
692    /// | Function | Description | Example |
693    /// |----------|-------------|---------|
694    /// | `re.extract(text, pattern, rewrite)` | Extract and rewrite with pattern | `re.extract('Hello World', r'(\\w+) (\\w+)', r'\\2, \\1')` |
695    /// | `re.capture(text, pattern)` | Capture first group | `re.capture('john@example.com', r'([^@]+)@')` |
696    /// | `re.captureN(text, pattern)` | Capture all groups as map | `re.captureN('2023-12-25', r'(\\d{4})-(\\d{2})-(\\d{2})')` |
697    ///
698    /// # CEL Syntax Impact
699    ///
700    /// When enabled, adds RE2-based regex functions in the `re` namespace:
701    /// - `re.extract()` performs extraction and rewriting in one operation
702    /// - `re.capture()` returns string of first capture group
703    /// - `re.captureN()` returns map with numbered/named capture groups
704    /// - Uses RE2 library for consistent performance and safety
705    /// - Supports named capture groups in `captureN()`
706    ///
707    /// # Examples
708    ///
709    /// ```rust
710    /// use cel_cxx::*;
711    /// 
712    /// let env = Env::builder()
713    ///     .with_ext_re(true)
714    ///     .build()?;
715    /// 
716    /// // Extract and rewrite
717    /// let program = env.compile(r#"re.extract('Hello World', r'(\w+) (\w+)', r'\2, \1')"#)?;
718    /// 
719    /// // Capture first group
720    /// let program2 = env.compile(r#"re.capture('john@example.com', r'([^@]+)@')"#)?;
721    /// 
722    /// // Capture all groups
723    /// let program3 = env.compile(r#"re.captureN('2023-12-25', r'(\d{4})-(\d{2})-(\d{2})')"#)?;
724    /// # Ok::<(), cel_cxx::Error>(())
725    /// ```
726    pub fn with_ext_re(mut self, enable: bool) -> Self {
727        self.options.enable_ext_re = enable;
728        self
729    }
730
731    /// Enables or disables the Sets extension.
732    ///
733    /// **Default**: Disabled (`false`)
734    ///
735    /// This extension provides functions for set-based operations on lists, such as containment
736    /// checking, equivalence testing, and intersection detection. Note that CEL does not have 
737    /// a native `set` type; these functions treat lists as sets.
738    ///
739    /// # Available Functions
740    ///
741    /// | Function | Description | Example |
742    /// |----------|-------------|---------|
743    /// | `sets.contains(list1, list2)` | Check if list1 contains all elements of list2 | `sets.contains([1,2,3], [2,3])` → `true` |
744    /// | `sets.equivalent(list1, list2)` | Check if lists are set equivalent | `sets.equivalent([1,2,3], [3,2,1])` → `true` |
745    /// | `sets.intersects(list1, list2)` | Check if lists have common elements | `sets.intersects([1,2], [2,3])` → `true` |
746    ///
747    /// # CEL Syntax Impact
748    ///
749    /// When enabled, adds set operations in the `sets` namespace:
750    /// - Treats lists as sets (order and duplicates don't matter for equivalence)
751    /// - Uses standard CEL equality for element comparison
752    /// - Supports type coercion (e.g., `1`, `1.0`, `1u` are considered equal)
753    /// - Empty list operations: `contains([], [])` → `true`, `intersects([], [])` → `false`
754    /// - Works with any comparable types
755    ///
756    /// # Examples
757    ///
758    /// ```rust
759    /// use cel_cxx::*;
760    /// 
761    /// let env = Env::builder()
762    ///     .with_ext_sets(true)
763    ///     .build()?;
764    /// 
765    /// // Set containment
766    /// let program = env.compile("sets.contains([1, 2, 3, 4], [2, 3])")?;
767    /// let result = program.evaluate(&Activation::new())?;
768    /// assert_eq!(result, Value::Bool(true));
769    /// 
770    /// // Set equivalence
771    /// let program2 = env.compile("sets.equivalent([1, 2, 3], [3, 2, 1])")?;
772    /// let result2 = program2.evaluate(&Activation::new())?;
773    /// assert_eq!(result2, Value::Bool(true));
774    /// 
775    /// // Set intersection
776    /// let program3 = env.compile("sets.intersects([1, 2], [2, 3])")?;
777    /// let result3 = program3.evaluate(&Activation::new())?;
778    /// assert_eq!(result3, Value::Bool(true));
779    /// # Ok::<(), cel_cxx::Error>(())
780    /// ```
781    pub fn with_ext_sets(mut self, enable: bool) -> Self {
782        self.options.enable_ext_sets = enable;
783        self
784    }
785
786    /// Enables or disables the Strings extension.
787    ///
788    /// **Default**: Disabled (`false`)
789    ///
790    /// This extension provides additional functions for string manipulation, including character
791    /// access, searching, extraction, case conversion, formatting, and advanced text processing
792    /// operations that go beyond the basic string operations in the standard library.
793    ///
794    /// # Available Functions
795    ///
796    /// | Function | Description | Example |
797    /// |----------|-------------|---------|
798    /// | `string.charAt(index)` | Get character at index | `'hello'.charAt(1)` → `'e'` |
799    /// | `string.indexOf(substring)` | Find first occurrence | `'hello'.indexOf('l')` → `2` |
800    /// | `string.indexOf(substring, start)` | Find from start position | `'hello'.indexOf('l', 3)` → `3` |
801    /// | `string.lastIndexOf(substring)` | Find last occurrence | `'hello'.lastIndexOf('l')` → `3` |
802    /// | `string.substring(start)` | Extract from start to end | `'hello'.substring(1)` → `'ello'` |
803    /// | `string.substring(start, end)` | Extract substring | `'hello'.substring(1, 4)` → `'ell'` |
804    /// | `strings.quote(string)` | Quote string for CEL | `strings.quote('hello')` → `'"hello"'` |
805    /// | `string.trim()` | Remove whitespace | `' hello '.trim()` → `'hello'` |
806    /// | `list.join(separator)` | Join strings | `['a','b'].join(',')` → `'a,b'` |
807    /// | `string.split(separator)` | Split string | `'a,b,c'.split(',')` → `['a','b','c']` |
808    /// | `string.lowerAscii()` | Convert to lowercase | `'HELLO'.lowerAscii()` → `'hello'` |
809    /// | `string.upperAscii()` | Convert to uppercase | `'hello'.upperAscii()` → `'HELLO'` |
810    /// | `string.replace(old, new)` | Replace all occurrences | `'hello'.replace('l','x')` → `'hexxo'` |
811    /// | `string.replace(old, new, count)` | Replace up to count | `'hello'.replace('l','x',1)` → `'hexlo'` |
812    /// | `string.format(args)` | Printf-style formatting | `'Hello %s'.format(['World'])` → `'Hello World'` |
813    /// | `string.reverse()` | Reverse string | `'hello'.reverse()` → `'olleh'` |
814    ///
815    /// # CEL Syntax Impact
816    ///
817    /// When enabled, adds advanced string manipulation capabilities:
818    /// - Zero-based indexing for character access and substring operations
819    /// - Safe out-of-bounds handling (empty string for invalid indices)
820    /// - ASCII-only case conversion (Unicode characters unchanged)
821    /// - Printf-style format placeholders: `%s`, `%d`, `%f`, `%.Nf`
822    /// - Efficient string processing with immutable operations
823    ///
824    /// # Examples
825    ///
826    /// ```rust
827    /// use cel_cxx::*;
828    /// 
829    /// let env = Env::builder()
830    ///     .with_ext_strings(true)
831    ///     .build()?;
832    /// 
833    /// // String searching and extraction
834    /// let program = env.compile("'hello world'.substring('hello world'.indexOf(' ') + 1)")?;
835    /// let result = program.evaluate(&Activation::new())?;
836    /// assert_eq!(result, Value::String("world".into()));
837    /// 
838    /// // String formatting
839    /// let program2 = env.compile("'Hello, %s!'.format(['Alice'])")?;
840    /// let result2 = program2.evaluate(&Activation::new())?;
841    /// assert_eq!(result2, Value::String("Hello, Alice!".into()));
842    /// 
843    /// // String processing pipeline
844    /// let program3 = env.compile("'  HELLO WORLD  '.trim().lowerAscii().replace(' ', '_')")?;
845    /// let result3 = program3.evaluate(&Activation::new())?;
846    /// assert_eq!(result3, Value::String("hello_world".into()));
847    /// # Ok::<(), cel_cxx::Error>(())
848    /// ```
849    pub fn with_ext_strings(mut self, enable: bool) -> Self {
850        self.options.enable_ext_strings = enable;
851        self
852    }
853
854    /// Enables or disables the select optimization extension.
855    ///
856    /// **Default**: Disabled (`false`)
857    ///
858    /// This is an optimization that can improve the performance of `select` expressions
859    /// (field access) by transforming them at compile time. It does not introduce new
860    /// user-visible functions but can change the evaluation cost of field access operations.
861    ///
862    /// # CEL Syntax Impact
863    ///
864    /// When enabled, provides compile-time optimizations for:
865    /// - Message field access operations
866    /// - Map key access patterns
867    /// - Nested field selection chains
868    /// - No new syntax or functions are added
869    /// - Transparent performance improvements
870    ///
871    /// # Examples
872    ///
873    /// ```rust
874    /// use cel_cxx::*;
875    /// 
876    /// let env = Env::builder()
877    ///     .with_ext_select_optimization(true)
878    ///     .build()?;
879    /// 
880    /// // Field access operations may be optimized
881    /// let program = env.compile("user.profile.settings.theme")?;
882    /// 
883    /// // Map access patterns may be optimized  
884    /// let program2 = env.compile("config['database']['host']")?;
885    /// # Ok::<(), cel_cxx::Error>(())
886    /// ```
887    pub fn with_ext_select_optimization(mut self, enable: bool) -> Self {
888        self.options.enable_ext_select_optimization = enable;
889        self
890    }
891
892    /// Registers a function (either global or member).
893    ///
894    /// This method allows you to register custom functions that can be called
895    /// from CEL expressions. The function can be either a global function or
896    /// a member function of a type.
897    ///
898    /// # Function Registration Process
899    ///
900    /// When you register a function, the system:
901    /// 1. Extracts type information from the function signature
902    /// 2. Creates type-safe conversion wrappers
903    /// 3. Stores both the type signature and implementation
904    /// 4. Updates the function marker type to track sync/async status
905    ///
906    /// # Zero-Annotation Benefits
907    ///
908    /// Functions are registered without explicit type annotations:
909    /// - Argument types are automatically inferred
910    /// - Return types are automatically determined
911    /// - Error handling is automatically supported for `Result<T, E>` returns
912    /// - Reference parameters like `&str` are handled safely
913    ///
914    /// # Arguments
915    ///
916    /// * `name` - The name of the function as it will appear in CEL expressions
917    /// * `member` - Whether this is a member function (`true`) or global function (`false`)
918    /// * `f` - The function implementation (function pointer, closure, etc.)
919    ///
920    /// # Type Parameters
921    ///
922    /// * `F` - The function implementation type
923    /// * `Ffm` - The function marker type (sync/async) inferred from the function
924    /// * `Args` - The argument tuple type (automatically inferred)
925    ///
926    /// # Returns
927    ///
928    /// A new `EnvBuilder` with updated function marker type. If this is the first
929    /// async function registered, the marker changes from `()` to `Async`.
930    ///
931    /// # Member vs Global Functions
932    ///
933    /// ## Global Functions
934    /// Called as `function_name(args...)`:
935    /// ```text
936    /// max(a, b)           // max function with two arguments
937    /// calculate(x, y, z)  // calculate function with three arguments
938    /// ```
939    ///
940    /// ## Member Functions  
941    /// Called as `object.method(args...)`:
942    /// ```text
943    /// text.contains(substring)    // contains method on string
944    /// list.size()                // size method on list
945    /// ```
946    ///
947    /// # Function Signature Support
948    ///
949    /// Supports various function signatures:
950    /// - **Simple functions**: `fn(T) -> U`
951    /// - **Functions with errors**: `fn(T) -> Result<U, E>`
952    /// - **Reference parameters**: `fn(&str, i64) -> String`
953    /// - **Multiple parameters**: Up to 10 parameters supported
954    /// - **Closures**: Move closures that capture environment
955    ///
956    /// # Errors
957    ///
958    /// Returns [`Error`] if:
959    /// - Function name conflicts with existing registration
960    /// - Function signature is invalid or unsupported
961    /// - Type inference fails
962    ///
963    /// # Examples
964    ///
965    /// ## Basic Functions
966    ///
967    /// ```rust
968    /// use cel_cxx::*;
969    ///
970    /// let builder = Env::builder()
971    ///     .register_function("add", false, |a: i64, b: i64| a + b)?
972    ///     .register_function("greet", false, |name: &str| format!("Hello, {}!", name))?;
973    /// # Ok::<(), cel_cxx::Error>(())
974    /// ```
975    ///
976    /// ## Member Functions
977    ///
978    /// ```rust
979    /// use cel_cxx::*;
980    ///
981    /// let builder = Env::builder()
982    ///     .register_function("contains", true, |text: &str, substr: &str| text.contains(substr))?
983    ///     .register_function("length", true, |text: &str| text.len() as i64)?;
984    ///
985    /// // Usage in expressions:
986    /// // text.contains("hello")
987    /// // text.length()
988    /// # Ok::<(), cel_cxx::Error>(())
989    /// ```
990    ///
991    /// ## Functions with Error Handling
992    ///
993    /// ```rust
994    /// use cel_cxx::*;
995    ///
996    /// let builder = Env::builder()
997    ///     .register_function("divide", false, |a: f64, b: f64| -> Result<f64, Error> {
998    ///         if b == 0.0 {
999    ///             Err(Error::invalid_argument("division by zero"))
1000    ///         } else {
1001    ///             Ok(a / b)
1002    ///         }
1003    ///     })?;
1004    /// # Ok::<(), cel_cxx::Error>(())
1005    /// ```
1006    ///
1007    /// ## Closures with Captured Data
1008    ///
1009    /// ```rust
1010    /// use cel_cxx::*;
1011    ///
1012    /// let multiplier = 5;
1013    /// let threshold = 100.0;
1014    ///
1015    /// let builder = Env::builder()
1016    ///     .register_function("scale", false, move |x: i64| x * multiplier)?
1017    ///     .register_function("check_limit", false, move |value: f64| value < threshold)?;
1018    /// # Ok::<(), cel_cxx::Error>(())
1019    /// ```
1020    pub fn register_function<F, Ffm, Args>(
1021        mut self,
1022        name: impl Into<String>,
1023        member: bool,
1024        f: F,
1025    ) -> Result<EnvBuilder<'f, <Ffm as FnMarkerAggr<Fm>>::Output, Rm>, Error>
1026    where
1027        F: IntoFunction<'f, Ffm, Args>,
1028        Ffm: FnMarker + FnMarkerAggr<Fm>,
1029        Args: Arguments,
1030    {
1031        self.function_registry.register(name, member, f)?;
1032
1033        Ok(EnvBuilder {
1034            function_registry: self.function_registry,
1035            variable_registry: self.variable_registry,
1036            options: self.options,
1037            _fn_marker: std::marker::PhantomData,
1038            _rt_marker: std::marker::PhantomData,
1039        })
1040    }
1041
1042    /// Registers a member function.
1043    ///
1044    /// This is a convenience method for registering member functions, equivalent to
1045    /// calling `register_function(name, true, f)`. Member functions are called using
1046    /// dot notation in CEL expressions: `object.method(args...)`.
1047    ///
1048    /// # Arguments
1049    ///
1050    /// * `name` - The method name as it will appear in CEL expressions
1051    /// * `f` - The function implementation
1052    ///
1053    /// # Member Function Semantics
1054    ///
1055    /// Member functions in CEL follow these patterns:
1056    /// - First parameter is the "receiver" (the object before the dot)
1057    /// - Additional parameters become method arguments
1058    /// - Called as `receiver.method(arg1, arg2, ...)`
1059    ///
1060    /// # Examples
1061    ///
1062    /// ## String Methods
1063    ///
1064    /// ```rust
1065    /// use cel_cxx::*;
1066    ///
1067    /// let builder = Env::builder()
1068    ///     .register_member_function("upper", |s: &str| s.to_uppercase())?
1069    ///     .register_member_function("contains", |s: &str, substr: &str| s.contains(substr))?
1070    ///     .register_member_function("repeat", |s: &str, n: i64| s.repeat(n as usize))?;
1071    ///
1072    /// // Usage in expressions:
1073    /// // "hello".upper()           -> "HELLO"
1074    /// // "hello world".contains("world") -> true
1075    /// // "abc".repeat(3)           -> "abcabcabc"
1076    /// # Ok::<(), cel_cxx::Error>(())
1077    /// ```
1078    ///
1079    /// ## Numeric Methods
1080    ///
1081    /// ```rust
1082    /// use cel_cxx::*;
1083    ///
1084    /// let builder = Env::builder()
1085    ///     .register_member_function("abs", |x: f64| x.abs())?
1086    ///     .register_member_function("pow", |x: f64, exp: f64| x.powf(exp))?;
1087    ///
1088    /// // Usage in expressions:
1089    /// // (-5.5).abs()     -> 5.5
1090    /// // (2.0).pow(3.0)   -> 8.0
1091    /// # Ok::<(), cel_cxx::Error>(())
1092    /// ```
1093    pub fn register_member_function<F, Ffm, Args>(
1094        mut self,
1095        name: impl Into<String>,
1096        f: F,
1097    ) -> Result<EnvBuilder<'f, <Ffm as FnMarkerAggr<Fm>>::Output, Rm>, Error>
1098    where
1099        F: IntoFunction<'f, Ffm, Args>,
1100        Ffm: FnMarker + FnMarkerAggr<Fm>,
1101        Args: Arguments,
1102    {
1103        self.function_registry.register_member(name, f)?;
1104
1105        Ok(EnvBuilder {
1106            function_registry: self.function_registry,
1107            variable_registry: self.variable_registry,
1108            options: self.options,
1109            _fn_marker: std::marker::PhantomData,
1110            _rt_marker: std::marker::PhantomData,
1111        })
1112    }
1113
1114    /// Registers a global function.
1115    ///
1116    /// This is a convenience method for registering global functions, equivalent to
1117    /// calling `register_function(name, false, f)`. Global functions are called directly
1118    /// by name in CEL expressions: `function_name(args...)`.
1119    ///
1120    /// # Arguments
1121    ///
1122    /// * `name` - The function name as it will appear in CEL expressions
1123    /// * `f` - The function implementation
1124    ///
1125    /// # Global Function Characteristics
1126    ///
1127    /// Global functions:
1128    /// - Are called directly by name without a receiver object
1129    /// - Can have 0 to 10 parameters
1130    /// - Support all CEL-compatible parameter and return types
1131    /// - Can capture environment variables (for closures)
1132    ///
1133    /// # Function Naming Guidelines
1134    ///
1135    /// - Use clear, descriptive names: `calculate_tax`, `format_date`
1136    /// - Follow CEL naming conventions (snake_case is recommended)
1137    /// - Avoid conflicts with built-in CEL functions
1138    /// - Consider namespacing for domain-specific functions: `math_sqrt`, `string_trim`
1139    ///
1140    /// # Examples
1141    ///
1142    /// ## Mathematical Functions
1143    ///
1144    /// ```rust
1145    /// use cel_cxx::*;
1146    ///
1147    /// let builder = Env::builder()
1148    ///     .register_global_function("add", |a: i64, b: i64| a + b)?
1149    ///     .register_global_function("multiply", |a: f64, b: f64| a * b)?
1150    ///     .register_global_function("max", |a: i64, b: i64| if a > b { a } else { b })?;
1151    ///
1152    /// // Usage in expressions:
1153    /// // add(10, 20)          -> 30
1154    /// // multiply(2.5, 4.0)   -> 10.0
1155    /// // max(15, 8)           -> 15
1156    /// # Ok::<(), cel_cxx::Error>(())
1157    /// ```
1158    ///
1159    /// ## String Processing Functions
1160    ///
1161    /// ```rust
1162    /// use cel_cxx::*;
1163    ///
1164    /// let builder = Env::builder()
1165    ///     .register_global_function("concat", |a: &str, b: &str| format!("{}{}", a, b))?
1166    ///     .register_global_function("trim_prefix", |s: &str, prefix: &str| {
1167    ///         s.strip_prefix(prefix).unwrap_or(s).to_string()
1168    ///     })?;
1169    ///
1170    /// // Usage in expressions:
1171    /// // concat("Hello, ", "World!")     -> "Hello, World!"
1172    /// // trim_prefix("prefixed_text", "prefixed_")  -> "text"
1173    /// # Ok::<(), cel_cxx::Error>(())
1174    /// ```
1175    ///
1176    /// ## Business Logic Functions
1177    ///
1178    /// ```rust
1179    /// use cel_cxx::*;
1180    ///
1181    /// let builder = Env::builder()
1182    ///     .register_global_function("calculate_discount", |price: f64, rate: f64| {
1183    ///         price * (1.0 - rate.min(1.0).max(0.0))
1184    ///     })?
1185    ///     .register_global_function("is_valid_email", |email: &str| {
1186    ///         email.contains('@') && email.contains('.')
1187    ///     })?;
1188    ///
1189    /// // Usage in expressions:
1190    /// // calculate_discount(100.0, 0.15)     -> 85.0
1191    /// // is_valid_email("user@domain.com")   -> true
1192    /// # Ok::<(), cel_cxx::Error>(())
1193    /// ```
1194    ///
1195    /// ## Functions with Complex Logic
1196    ///
1197    /// ```rust
1198    /// use cel_cxx::*;
1199    /// use std::collections::HashMap;
1200    ///
1201    /// // Function that processes collections
1202    /// let builder = Env::builder()
1203    ///     .register_global_function("sum_positive", |numbers: Vec<i64>| {
1204    ///         numbers.iter().filter(|&x| *x > 0).sum::<i64>()
1205    ///     })?;
1206    ///
1207    /// // Usage in expressions:
1208    /// // sum_positive([1, -2, 3, -4, 5])  -> 9
1209    /// # Ok::<(), cel_cxx::Error>(())
1210    /// ```
1211    pub fn register_global_function<F, Ffm, Args>(
1212        mut self,
1213        name: impl Into<String>,
1214        f: F,
1215    ) -> Result<EnvBuilder<'f, <Ffm as FnMarkerAggr<Fm>>::Output, Rm>, Error>
1216    where
1217        F: IntoFunction<'f, Ffm, Args>,
1218        Ffm: FnMarker + FnMarkerAggr<Fm>,
1219        Args: Arguments,
1220    {
1221        self.function_registry.register_global(name, f)?;
1222
1223        Ok(EnvBuilder {
1224            function_registry: self.function_registry,
1225            variable_registry: self.variable_registry,
1226            options: self.options,
1227            _fn_marker: std::marker::PhantomData,
1228            _rt_marker: std::marker::PhantomData,
1229        })
1230    }
1231
1232    /// Declares a function signature without providing an implementation.
1233    ///
1234    /// This is useful when you want to declare that a function exists for
1235    /// type checking purposes, but will provide the implementation later
1236    /// via activation bindings.
1237    ///
1238    /// # Arguments
1239    ///
1240    /// * `name` - The name of the function
1241    /// * `member` - Whether this is a member function (`true`) or global function (`false`)
1242    ///
1243    /// # Type Parameters
1244    ///
1245    /// * `D` - The function declaration type that specifies the signature
1246    pub fn declare_function<D>(
1247        mut self,
1248        name: impl Into<String>,
1249        member: bool,
1250    ) -> Result<Self, Error>
1251    where
1252        D: FunctionDecl,
1253    {
1254        self.function_registry.declare::<D>(name, member)?;
1255        Ok(EnvBuilder {
1256            function_registry: self.function_registry,
1257            variable_registry: self.variable_registry,
1258            options: self.options,
1259            _fn_marker: std::marker::PhantomData,
1260            _rt_marker: std::marker::PhantomData,
1261        })
1262    }
1263
1264    /// Declares a member function signature without providing an implementation.
1265    ///
1266    /// # Arguments
1267    ///
1268    /// * `name` - The name of the member function
1269    ///
1270    /// # Type Parameters
1271    ///
1272    /// * `D` - The function declaration type that specifies the signature
1273    pub fn declare_member_function<D>(mut self, name: impl Into<String>) -> Result<Self, Error>
1274    where
1275        D: FunctionDecl,
1276    {
1277        self.function_registry.declare_member::<D>(name)?;
1278        Ok(EnvBuilder {
1279            function_registry: self.function_registry,
1280            variable_registry: self.variable_registry,
1281            options: self.options,
1282            _fn_marker: std::marker::PhantomData,
1283            _rt_marker: std::marker::PhantomData,
1284        })
1285    }
1286
1287    /// Declares a global function signature without providing an implementation.
1288    ///
1289    /// # Arguments
1290    ///
1291    /// * `name` - The name of the global function
1292    ///
1293    /// # Type Parameters
1294    ///
1295    /// * `D` - The function declaration type that specifies the signature
1296    pub fn declare_global_function<D>(mut self, name: impl Into<String>) -> Result<Self, Error>
1297    where
1298        D: FunctionDecl,
1299    {
1300        self.function_registry.declare_global::<D>(name)?;
1301        Ok(EnvBuilder {
1302            function_registry: self.function_registry,
1303            variable_registry: self.variable_registry,
1304            options: self.options,
1305            _fn_marker: std::marker::PhantomData,
1306            _rt_marker: std::marker::PhantomData,
1307        })
1308    }
1309
1310    /// Defines a constant value that can be referenced in expressions.
1311    ///
1312    /// Constants are immutable values that are resolved at compile time.
1313    ///
1314    /// # Arguments
1315    ///
1316    /// * `name` - The name of the constant
1317    /// * `value` - The constant value
1318    ///
1319    /// # Examples
1320    ///
1321    /// ```rust,no_run
1322    /// use cel_cxx::*;
1323    ///
1324    /// let builder = Env::builder()
1325    ///     .define_constant("PI", 3.14159)
1326    ///     .unwrap();
1327    /// # Ok::<(), cel_cxx::Error>(())
1328    /// ```
1329    pub fn define_constant<T>(mut self, name: impl Into<String>, value: T) -> Result<Self, Error>
1330    where
1331        T: IntoConstant,
1332    {
1333        self.variable_registry.define_constant(name, value)?;
1334        Ok(EnvBuilder {
1335            function_registry: self.function_registry,
1336            variable_registry: self.variable_registry,
1337            options: self.options,
1338            _fn_marker: std::marker::PhantomData,
1339            _rt_marker: std::marker::PhantomData,
1340        })
1341    }
1342
1343    /// Declares a variable of a specific type.
1344    ///
1345    /// This declares that a variable of the given name and type may be
1346    /// provided during evaluation. The actual value must be bound in
1347    /// the activation when evaluating expressions.
1348    ///
1349    /// # Arguments
1350    ///
1351    /// * `name` - The name of the variable
1352    ///
1353    /// # Type Parameters
1354    ///
1355    /// * `T` - The type of the variable
1356    ///
1357    /// # Examples
1358    ///
1359    /// ```rust,no_run
1360    /// use cel_cxx::*;
1361    ///
1362    /// let builder = Env::builder()
1363    ///     .declare_variable::<String>("user_name")?
1364    ///     .declare_variable::<i64>("age")?;
1365    ///
1366    /// # Ok::<(), cel_cxx::Error>(())
1367    /// ```
1368    pub fn declare_variable<T>(mut self, name: impl Into<String>) -> Result<Self, Error>
1369    where
1370        T: TypedValue,
1371    {
1372        self.variable_registry.declare::<T>(name)?;
1373        Ok(EnvBuilder {
1374            function_registry: self.function_registry,
1375            variable_registry: self.variable_registry,
1376            options: self.options,
1377            _fn_marker: std::marker::PhantomData,
1378            _rt_marker: std::marker::PhantomData,
1379        })
1380    }
1381
1382    /// Builds the environment from the configured builder.
1383    ///
1384    /// This method consumes the builder and creates the final [`Env`] instance
1385    /// that can be used to compile CEL expressions.
1386    ///
1387    /// # Returns
1388    ///
1389    /// Returns a [`Result`] containing the built [`Env`] or an [`Error`] if
1390    /// the environment could not be created.
1391    ///
1392    /// # Examples
1393    ///
1394    /// ```rust,no_run
1395    /// use cel_cxx::*;
1396    ///
1397    /// let env = Env::builder()
1398    ///     .declare_variable::<String>("name")?
1399    ///     .build()?;
1400    /// # Ok::<(), cel_cxx::Error>(())
1401    /// ```
1402    ///
1403    /// # Errors
1404    ///
1405    /// Returns an error if the environment configuration is invalid or
1406    /// if the underlying CEL environment cannot be created.
1407    pub fn build(self) -> Result<Env<'f, Fm, Rm>, Error> {
1408        let inner = EnvInner::new_with_registries(self.function_registry, self.variable_registry, self.options)
1409            .map_err(|ffi_status| ffi::error_to_rust(&ffi_status))?;
1410        let env = Env {
1411            inner: Arc::new(inner),
1412            _fn_marker: self._fn_marker,
1413            _rt_marker: self._rt_marker,
1414        };
1415        Ok(env)
1416    }
1417}
1418
1419#[cfg(feature = "async")]
1420#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1421const _: () = {
1422    use crate::r#async::*;
1423
1424    impl<'f, Rm: RuntimeMarker> Env<'f, (), Rm> {
1425        /// Forces conversion to an async environment.
1426        ///
1427        /// This method converts a synchronous environment to an asynchronous one,
1428        /// allowing it to work with async functions and evaluation.
1429        ///
1430        /// # Type Parameters
1431        ///
1432        /// * `Rt` - The async runtime type to use
1433        ///
1434        /// # Examples
1435        ///
1436        /// ```rust,no_run
1437        /// # #[cfg(feature = "async")]
1438        /// # {
1439        /// use cel_cxx::*;
1440        ///
1441        /// let sync_env = Env::builder().build()?;
1442        /// let async_env = sync_env.force_async();
1443        /// # }
1444        /// # Ok::<(), cel_cxx::Error>(())
1445        /// ```
1446        pub fn force_async(self) -> Env<'f, Async, Rm> {
1447            Env {
1448                inner: self.inner,
1449                _fn_marker: std::marker::PhantomData,
1450                _rt_marker: std::marker::PhantomData,
1451            }
1452        }
1453    }
1454
1455    impl<'f, Rm: RuntimeMarker> EnvBuilder<'f, (), Rm> {
1456        /// Forces conversion to an async environment builder.
1457        ///
1458        /// This method converts a synchronous environment builder to an asynchronous one,
1459        /// allowing it to register async functions and build async environments.
1460        ///
1461        /// # Examples
1462        ///
1463        /// ```rust,no_run
1464        /// # #[cfg(feature = "async")]
1465        /// # {
1466        /// use cel_cxx::*;
1467        ///
1468        /// let async_builder = Env::builder().force_async();
1469        /// # }
1470        /// ```
1471        pub fn force_async(self) -> EnvBuilder<'f, Async, Rm> {
1472            EnvBuilder {
1473                function_registry: self.function_registry,
1474                variable_registry: self.variable_registry,
1475                options: self.options,
1476                _fn_marker: std::marker::PhantomData,
1477                _rt_marker: std::marker::PhantomData,
1478            }
1479        }
1480    }
1481
1482    impl<'f, Fm: FnMarker> Env<'f, Fm, ()> {
1483        /// Sets the async runtime for this environment.
1484        ///
1485        /// This method specifies which async runtime should be used for
1486        /// asynchronous evaluation of expressions.
1487        ///
1488        /// # Type Parameters
1489        ///
1490        /// * `Rt` - The runtime type to use (must implement [`Runtime`])
1491        ///
1492        /// # Examples
1493        ///
1494        /// ```rust,no_run
1495        /// # #[cfg(feature = "async")]
1496        /// # {
1497        /// use cel_cxx::*;
1498        ///
1499        /// let env = Env::builder()
1500        ///     .build()?
1501        ///     .use_runtime::<Tokio>();
1502        /// # }
1503        /// # Ok::<(), cel_cxx::Error>(())
1504        /// ```
1505        pub fn use_runtime<Rt: Runtime>(self) -> Env<'f, Fm, Rt> {
1506            let inner = self.inner.clone();
1507            Env {
1508                inner,
1509                _fn_marker: self._fn_marker,
1510                _rt_marker: std::marker::PhantomData,
1511            }
1512        }
1513
1514        /// Configures the environment to use the Tokio async runtime.
1515        ///
1516        /// This is a convenience method for setting the runtime to Tokio.
1517        /// Requires the `tokio` feature to be enabled.
1518        ///
1519        /// # Examples
1520        ///
1521        /// ```rust,no_run
1522        /// # #[cfg(all(feature = "async", feature = "tokio"))]
1523        /// # {
1524        /// use cel_cxx::*;
1525        ///
1526        /// let env = Env::builder()
1527        ///     .build()?
1528        ///     .use_tokio();
1529        /// # }
1530        /// # Ok::<(), cel_cxx::Error>(())
1531        /// ```
1532        #[cfg(feature = "tokio")]
1533        #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
1534        pub fn use_tokio(self) -> Env<'f, Fm, Tokio> {
1535            self.use_runtime::<Tokio>()
1536        }
1537
1538        /// Configures the environment to use the async-std runtime.
1539        ///
1540        /// This is a convenience method for setting the runtime to async-std.
1541        /// Requires the `async-std` feature to be enabled.
1542        ///
1543        /// # Examples
1544        ///
1545        /// ```rust,no_run
1546        /// # #[cfg(all(feature = "async", feature = "async-std"))]
1547        /// # {
1548        /// use cel_cxx::*;
1549        ///
1550        /// let env = Env::builder()
1551        ///     .build()?
1552        ///     .use_async_std();
1553        /// # }
1554        /// # Ok::<(), cel_cxx::Error>(())
1555        /// ```
1556        #[cfg(feature = "async-std")]
1557        #[cfg_attr(docsrs, doc(cfg(feature = "async-std")))]
1558        pub fn use_async_std(self) -> Env<'f, Fm, AsyncStd> {
1559            self.use_runtime::<AsyncStd>()
1560        }
1561
1562        /// Configures the environment to use the smol runtime.
1563        ///
1564        /// This is a convenience method for setting the runtime to smol.
1565        /// Requires the `smol` feature to be enabled.
1566        ///
1567        /// # Examples
1568        ///
1569        /// ```rust,no_run
1570        /// # #[cfg(feature = "async")]
1571        /// # {
1572        /// use cel_cxx::*;
1573        ///
1574        /// let env = Env::builder().use_smol();
1575        /// # }
1576        /// # Ok::<(), cel_cxx::Error>(())
1577        /// ```
1578        #[cfg(feature = "smol")]
1579        #[cfg_attr(docsrs, doc(cfg(feature = "smol")))]
1580        pub fn use_smol(self) -> Env<'f, Fm, Smol> {
1581            self.use_runtime::<Smol>()
1582        }
1583    }
1584
1585    impl<'f, Fm: FnMarker> EnvBuilder<'f, Fm, ()> {
1586        /// Sets the async runtime for the environment builder.
1587        ///
1588        /// This method specifies which async runtime should be used by
1589        /// environments built from this builder.
1590        ///
1591        /// # Type Parameters
1592        ///
1593        /// * `Rt` - The runtime type to use (must implement [`Runtime`])
1594        ///
1595        /// # Examples
1596        ///
1597        /// ```rust,no_run
1598        /// # #[cfg(feature = "async")]
1599        /// # {
1600        /// use cel_cxx::*;
1601        ///
1602        /// let builder = Env::builder().use_runtime::<Tokio>();
1603        /// # }
1604        /// ```
1605        pub fn use_runtime<Rt: Runtime>(self) -> EnvBuilder<'f, Fm, Rt> {
1606            EnvBuilder {
1607                function_registry: self.function_registry,
1608                variable_registry: self.variable_registry,
1609                options: self.options,
1610                _fn_marker: self._fn_marker,
1611                _rt_marker: std::marker::PhantomData,
1612            }
1613        }
1614
1615        /// Configures the builder to use the Tokio async runtime.
1616        ///
1617        /// This is a convenience method for setting the runtime to Tokio.
1618        /// Requires the `tokio` feature to be enabled.
1619        ///
1620        /// # Examples
1621        ///
1622        /// ```rust,no_run
1623        /// # #[cfg(all(feature = "async", feature = "tokio"))]
1624        /// # {
1625        /// use cel_cxx::*;
1626        ///
1627        /// let builder = Env::builder().use_tokio();
1628        /// # }
1629        /// ```
1630        #[cfg(feature = "tokio")]
1631        #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
1632        pub fn use_tokio(self) -> EnvBuilder<'f, Fm, Tokio> {
1633            self.use_runtime::<Tokio>()
1634        }
1635
1636        /// Configures the builder to use the async-std runtime.
1637        ///
1638        /// This is a convenience method for setting the runtime to async-std.
1639        /// Requires the `async-std` feature to be enabled.
1640        ///
1641        /// # Examples
1642        ///
1643        /// ```rust,no_run
1644        /// # #[cfg(all(feature = "async", feature = "async-std"))]
1645        /// # {
1646        /// use cel_cxx::*;
1647        ///
1648        /// let builder = Env::builder().use_async_std();
1649        /// # }
1650        /// ```
1651        #[cfg(feature = "async-std")]
1652        #[cfg_attr(docsrs, doc(cfg(feature = "async-std")))]
1653        pub fn use_async_std(self) -> EnvBuilder<'f, Fm, AsyncStd> {
1654            self.use_runtime::<AsyncStd>()
1655        }
1656
1657        /// Configures the builder to use the smol runtime.
1658        ///
1659        /// This is a convenience method for setting the runtime to smol.
1660        /// Requires the `smol` feature to be enabled.
1661        ///
1662        /// # Examples
1663        ///
1664        /// ```rust,no_run
1665        /// # #[cfg(feature = "async")]
1666        /// # {
1667        /// use cel_cxx::*;
1668        ///
1669        /// let builder = Env::builder().use_smol();
1670        /// # }
1671        /// ```
1672        #[cfg(feature = "smol")]
1673        #[cfg_attr(docsrs, doc(cfg(feature = "smol")))]
1674        pub fn use_smol(self) -> EnvBuilder<'f, Fm, Smol> {
1675            self.use_runtime::<Smol>()
1676        }
1677    }
1678};
1679
1680impl<'f, Fm: FnMarker, Rm: RuntimeMarker> std::fmt::Debug for Env<'f, Fm, Rm> {
1681    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1682        f.debug_struct("Env").field("inner", &self.inner).finish()
1683    }
1684}
1685
1686impl<'f, Fm: FnMarker, Rm: RuntimeMarker> Clone for Env<'f, Fm, Rm> {
1687    fn clone(&self) -> Self {
1688        Env {
1689            inner: self.inner.clone(),
1690            _fn_marker: self._fn_marker,
1691            _rt_marker: self._rt_marker,
1692        }
1693    }
1694}
1695
1696impl<'f, Fm: FnMarker, Rm: RuntimeMarker> std::fmt::Debug for EnvBuilder<'f, Fm, Rm> {
1697    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1698        f.debug_struct("EnvBuilder")
1699            .field("function_registry", &self.function_registry)
1700            .field("variable_registry", &self.variable_registry)
1701            .finish()
1702    }
1703}
1704
1705impl<'f, Fm: FnMarker, Rm: RuntimeMarker> Default for EnvBuilder<'f, Fm, Rm> {
1706    fn default() -> Self {
1707        EnvBuilder {
1708            function_registry: FunctionRegistry::new(),
1709            variable_registry: VariableRegistry::new(),
1710            options: EnvInnerOptions::default(),
1711            _fn_marker: std::marker::PhantomData,
1712            _rt_marker: std::marker::PhantomData,
1713        }
1714    }
1715}