Struct Env

Source
pub struct Env<'f, Fm: FnMarker = (), Rm: RuntimeMarker = ()> { /* private fields */ }
Expand description

CEL expression evaluation environment.

The Env struct represents a CEL environment that can compile expressions into programs. It encapsulates function registries, variable declarations, and type information needed for expression compilation.

§Type Parameters

  • 'f: Lifetime of functions registered in this environment
  • Fm: Function marker type indicating sync/async function support
  • Rm: Runtime marker type indicating the async runtime (if any)

§Examples

§Basic Usage

use cel_cxx::*;

let env = Env::builder()
    .declare_variable::<String>("name")?
    .build()?;
     
let program = env.compile("'Hello, ' + name")?;

§With Custom Functions

use cel_cxx::*;

let env = Env::builder()
    .register_global_function("add", |x: i64, y: i64| -> i64 { x + y })?
    .build()?;
     
let program = env.compile("add(10, 20)")?;

Implementations§

Source§

impl<'f> Env<'f>

Source

pub fn builder() -> EnvBuilder<'f, ()>

Creates a new environment builder.

This is the starting point for creating a CEL environment. The builder allows you to register functions, declare variables, and configure the environment before building it.

§Examples
use cel_cxx::*;

let builder = Env::builder();
Examples found in repository?
examples/basic.rs (line 11)
7fn main() -> Result<(), Error> {
8    println!("🚀 CEL-CXX Basic Example\n");
9
10    // Create an environment with variables and functions
11    let env = Env::builder()
12        .declare_variable::<String>("name")?
13        .declare_variable::<i64>("age")?
14        .register_global_function("greet", |name: &str| format!("Hello, {}!", name))?
15        .register_global_function("is_adult", |age: i64| age >= 18)?
16        .build()?;
17
18    // Compile and evaluate expressions
19    let expressions = vec![
20        "greet(name)",
21        "is_adult(age)",
22        "'Name: ' + name + ', Age: ' + string(age)",
23        "age >= 18 ? 'adult' : 'minor'",
24    ];
25
26    let activation = Activation::new()
27        .bind_variable("name", "Alice")?
28        .bind_variable("age", 25i64)?;
29
30    for expr in expressions {
31        let program = env.compile(expr)?;
32        let result = program.evaluate(&activation)?;
33        println!("{} = {}", expr, result);
34    }
35
36    println!("\n✅ Basic example completed!");
37    Ok(())
38}
More examples
Hide additional examples
examples/comprehensive.rs (line 149)
146fn demo1_basic_operations() -> Result<(), Error> {
147    println!("📌 Demo 1: Basic Expressions & Zero-Annotation Functions");
148
149    let env = Env::builder()
150        .declare_variable::<String>("name")?
151        .declare_variable::<i64>("age")?
152        .declare_variable::<f64>("score")?
153        // ✨ Zero-annotation functions - types automatically inferred!
154        .register_global_function("greet", |name: &str| format!("Hello, {}!", name))?
155        .register_global_function("is_adult", |age: i64| age >= 18)?
156        .register_global_function("grade", |score: f64| -> String {
157            match score {
158                90.0..=100.0 => "A".to_string(),
159                80.0..=89.9 => "B".to_string(),
160                70.0..=79.9 => "C".to_string(),
161                60.0..=69.9 => "D".to_string(),
162                _ => "F".to_string(),
163            }
164        })?
165        .register_global_function("calculate_discount", |age: i64, score: f64| -> f64 {
166            let base_discount = if age >= 65 { 0.2 } else { 0.0 };
167            let score_bonus = if score >= 90.0 { 0.1 } else { 0.0 };
168            base_discount + score_bonus
169        })?
170        .build()?;
171
172    // Test basic expressions including simple arithmetic
173    let test_cases = vec![
174        ("1 + 1", "Alice", 25i64, 95.0, "Simple arithmetic"),
175        (
176            "greet(name)",
177            "Alice",
178            25i64,
179            95.0,
180            "Function with string parameter",
181        ),
182        ("is_adult(age)", "Bob", 16i64, 85.0, "Boolean function"),
183        (
184            "grade(score)",
185            "Charlie",
186            30i64,
187            78.5,
188            "String return function",
189        ),
190        (
191            "calculate_discount(age, score)",
192            "Diana",
193            67i64,
194            92.0,
195            "Multi-parameter function",
196        ),
197    ];
198
199    for (expr, name, age, score, description) in test_cases {
200        let program = env.compile(expr)?;
201        let activation = Activation::new()
202            .bind_variable("name", name)?
203            .bind_variable("age", age)?
204            .bind_variable("score", score)?;
205
206        let result = program.evaluate(&activation)?;
207        println!("  {} = {} ({})", expr, result, description);
208    }
209
210    println!();
211    Ok(())
212}
213
214/// Demo 2: Variable binding and providers
215fn demo2_variable_operations() -> Result<(), Error> {
216    println!("📌 Demo 2: Variable Binding & Providers");
217
218    let env = Env::builder()
219        .declare_variable::<i64>("a")?
220        .declare_variable::<i64>("b")?
221        .declare_global_function::<fn() -> i64>("get_const")?
222        .register_global_function("multiply", |x: i64, y: i64| x * y)?
223        .build()?;
224
225    // Test direct variable binding
226    {
227        println!("  Variable binding:");
228        let program = env.compile("a + b")?;
229        let activation = Activation::new()
230            .bind_variable("a", 10)?
231            .bind_variable("b", 20)?;
232        let result = program.evaluate(&activation)?;
233        println!("    a + b = {} (direct binding)", result);
234    }
235
236    // Test variable provider binding
237    {
238        println!("  Variable provider binding:");
239        let program = env.compile("a * b")?;
240        let activation = Activation::new()
241            .bind_variable("a", 5)?
242            .bind_variable_provider("b", || -> Result<i64, Error> {
243                println!("    Provider called for variable 'b'");
244                Ok(7)
245            })?;
246        let result = program.evaluate(&activation)?;
247        println!("    a * b = {} (provider binding)", result);
248    }
249
250    // Test function declaration and binding
251    {
252        println!("  Function declaration & binding:");
253        let program = env.compile("get_const() + multiply(a, 3)")?;
254        let activation = Activation::new()
255            .bind_variable("a", 4)?
256            .bind_global_function("get_const", || -> Result<i64, Error> { Ok(100) })?;
257        let result = program.evaluate(&activation)?;
258        println!(
259            "    get_const() + multiply(a, 3) = {} (function binding)",
260            result
261        );
262    }
263
264    println!();
265    Ok(())
266}
267
268/// Demo 3: Opaque types with member functions
269fn demo3_opaque_member_functions() -> Result<(), Error> {
270    println!("📌 Demo 3: Opaque Types & Member Functions");
271
272    let env = Env::builder()
273        .declare_variable::<Student>("student")?
274        // ✨ Register struct methods directly using RustType::method_name syntax
275        .register_member_function("get_name", Student::get_name)?
276        .register_member_function("get_age", Student::get_age)?
277        .register_member_function("get_grade", Student::get_grade)?
278        .register_member_function("is_passing", Student::is_passing)?
279        .register_member_function("has_subject", Student::has_subject)?
280        .register_member_function("get_letter_grade", Student::get_letter_grade)?
281        .build()?;
282
283    let student = Student {
284        name: "John Doe".to_string(),
285        age: 18,
286        grade: 87.5,
287        subjects: vec!["Math".to_string(), "Physics".to_string()],
288    };
289
290    let activation = Activation::new().bind_variable("student", student)?;
291
292    let test_expressions = vec![
293        ("student.get_name()", "Get student name"),
294        ("student.get_age()", "Get student age"),
295        ("student.get_grade()", "Get numerical grade"),
296        ("student.get_letter_grade()", "Get letter grade"),
297        ("student.is_passing()", "Check if passing"),
298        ("student.has_subject('Math')", "Check if has Math subject"),
299        (
300            "student.has_subject('Chemistry')",
301            "Check if has Chemistry subject",
302        ),
303    ];
304
305    for (expr, description) in test_expressions {
306        let program = env.compile(expr)?;
307        let result = program.evaluate(&activation)?;
308        println!("  {} = {} ({})", expr, result, description);
309    }
310
311    println!();
312    Ok(())
313}
314
315/// Demo 4: Type conversions and standard Rust types
316fn demo4_type_conversions() -> Result<(), Error> {
317    println!("📌 Demo 4: Type Conversions & Standard Rust Types");
318
319    // Functions returning different types (both direct values and Results)
320    fn return_string_direct() -> String {
321        "hello world".to_string()
322    }
323    fn return_int_result() -> Result<i64, std::io::Error> {
324        Ok(42)
325    }
326    fn return_list() -> Vec<i64> {
327        vec![1, 2, 3, 4, 5]
328    }
329    fn return_map() -> HashMap<String, i64> {
330        let mut map = HashMap::new();
331        map.insert("key1".to_string(), 100);
332        map.insert("key2".to_string(), 200);
333        map
334    }
335    fn return_optional_some() -> Option<String> {
336        Some("optional value".to_string())
337    }
338    fn return_optional_none() -> Option<String> {
339        None
340    }
341
342    let env = Env::builder()
343        .register_global_function("return_string_direct", return_string_direct)?
344        .register_global_function("return_int_result", return_int_result)?
345        .register_global_function("return_list", return_list)?
346        .register_global_function("return_map", return_map)?
347        .register_global_function("return_optional_some", return_optional_some)?
348        .register_global_function("return_optional_none", return_optional_none)?
349        .build()?;
350
351    let test_cases = vec![
352        ("return_string_direct()", "String conversion"),
353        ("return_int_result()", "Result<i64> conversion"),
354        ("return_list()", "Vec<i64> conversion"),
355        ("return_map()", "HashMap conversion"),
356        ("return_optional_some()", "Option<String> Some conversion"),
357        ("return_optional_none()", "Option<String> None conversion"),
358    ];
359
360    for (expr, description) in test_cases {
361        let program = env.compile(expr)?;
362        let result = program.evaluate(())?;
363        println!("  {} = {} ({})", expr, result, description);
364
365        // Demonstrate type conversion back to Rust types
366        match expr {
367            "return_string_direct()" => {
368                let rust_string: String = result
369                    .try_into()
370                    .map_err(|_| Error::invalid_argument("string conversion failed".to_string()))?;
371                println!("    Converted back to Rust String: '{}'", rust_string);
372            }
373            "return_int_result()" => {
374                let rust_int: i64 = result
375                    .try_into()
376                    .map_err(|_| Error::invalid_argument("int conversion failed".to_string()))?;
377                println!("    Converted back to Rust i64: {}", rust_int);
378            }
379            "return_list()" => {
380                let rust_list: Vec<i64> = result
381                    .try_into()
382                    .map_err(|_| Error::invalid_argument("list conversion failed".to_string()))?;
383                println!("    Converted back to Rust Vec<i64>: {:?}", rust_list);
384            }
385            _ => {}
386        }
387    }
388
389    println!();
390    Ok(())
391}
392
393/// Demo 5: Generic functions and type annotations
394fn demo5_generic_functions() -> Result<(), Error> {
395    println!("📌 Demo 5: Generic Functions & Function Overloads");
396
397    // Generic function that counts items in any Vec<T>
398    fn count_items<T>(items: Vec<T>) -> i64 {
399        items.len() as i64
400    }
401
402    // Generic function that processes maps
403    fn get_map_size<K, V>(map: HashMap<K, V>) -> i64 {
404        map.len() as i64
405    }
406
407    // Function working with references in containers
408    fn join_strings(strings: Vec<&str>, separator: &str) -> String {
409        strings.join(separator)
410    }
411
412    let env = Env::builder()
413        .declare_variable::<Vec<String>>("string_list")?
414        .declare_variable::<Vec<i64>>("int_list")?
415        .declare_variable::<HashMap<String, i64>>("score_map")?
416        .declare_variable::<Vec<f64>>("floats")?
417        // Register generic functions with specific type annotations
418        .register_global_function("count_strings", count_items::<String>)?
419        .register_global_function("count_ints", count_items::<i64>)?
420        .register_global_function("get_string_map_size", get_map_size::<String, i64>)?
421        .register_global_function("join_strings", join_strings)?
422        // Multiple functions with same name, different signatures (overloads)
423        .register_global_function("process", |x: i64| x * 2)?
424        .register_global_function("process", |x: f64| (x * 2.0).round())?
425        .register_global_function("process", |x: String| x.to_uppercase())?
426        // Overloaded member functions for different container types
427        .register_member_function("sum", |numbers: Vec<i64>| numbers.iter().sum::<i64>())?
428        .register_member_function("sum", |floats: Vec<f64>| floats.iter().sum::<f64>())?
429        .build()?;
430
431    let test_cases = vec![
432        // Generic function tests
433        ("count_strings(string_list)", "Count strings in list"),
434        ("count_ints(int_list)", "Count integers in list"),
435        ("get_string_map_size(score_map)", "Get map size"),
436        ("join_strings(string_list, ' ')", "Join strings with space"),
437        // Function overload tests
438        ("process(42)", "Process integer (multiply by 2)"),
439        ("process(3.14)", "Process float (multiply by 2, round)"),
440        ("process('hello')", "Process string (uppercase)"),
441        ("int_list.sum()", "Sum integers"),
442        ("floats.sum()", "Sum floats"),
443    ];
444
445    let activation = Activation::new()
446        .bind_variable(
447            "string_list",
448            vec!["hello".to_string(), "world".to_string(), "rust".to_string()],
449        )?
450        .bind_variable("int_list", vec![1, 2, 3, 4, 5, 6])?
451        .bind_variable("floats", vec![1.5, 2.7, 3.143, 4.0])?
452        .bind_variable("score_map", {
453            let mut map = HashMap::new();
454            map.insert("alice".to_string(), 95);
455            map.insert("bob".to_string(), 87);
456            map.insert("charlie".to_string(), 92);
457            map
458        })?;
459
460    for (expr, description) in test_cases {
461        let program = env.compile(expr)?;
462        let result = program.evaluate(&activation)?;
463        println!("  {} = {} ({})", expr, result, description);
464    }
465
466    println!();
467    Ok(())
468}
469
470/// Demo 6: Error handling with different error types including Box<dyn std::error::Error>
471fn demo6_error_handling() -> Result<(), Error> {
472    println!("📌 Demo 6: Error Handling & Validation");
473
474    let env = Env::builder()
475        .declare_variable::<String>("input")?
476        .declare_variable::<i64>("divisor")?
477        .declare_variable::<String>("email")?
478        // Functions returning different error types using thiserror-derived types
479        .register_global_function("safe_parse", |s: &str| -> Result<i64, ValidationError> {
480            s.parse::<i64>()
481                .map_err(|e| ValidationError::ParseError(e.to_string()))
482        })?
483        .register_global_function(
484            "safe_divide",
485            |a: i64, b: i64| -> Result<f64, ValidationError> {
486                if b == 0 {
487                    Err(ValidationError::DivisionByZero)
488                } else {
489                    Ok(a as f64 / b as f64)
490                }
491            },
492        )?
493        // Additional validation functions with ValidationError
494        .register_global_function(
495            "validate_email",
496            |email: &str| -> Result<bool, ValidationError> {
497                if email.is_empty() {
498                    return Err(ValidationError::EmailError(
499                        "Email cannot be empty".to_string(),
500                    ));
501                }
502                if !email.contains('@') {
503                    return Err(ValidationError::EmailError(
504                        "Email must contain @ symbol".to_string(),
505                    ));
506                }
507                if !email.contains('.') {
508                    return Err(ValidationError::EmailError(
509                        "Email must contain . symbol".to_string(),
510                    ));
511                }
512                let parts: Vec<&str> = email.split('@').collect();
513                if parts.len() != 2 {
514                    return Err(ValidationError::EmailError(
515                        "Email must contain exactly one @ symbol".to_string(),
516                    ));
517                }
518                if parts[0].is_empty() || parts[1].is_empty() {
519                    return Err(ValidationError::EmailError(
520                        "Email local and domain parts cannot be empty".to_string(),
521                    ));
522                }
523                Ok(true)
524            },
525        )?
526        .register_global_function(
527            "validate_age",
528            |age: i64| -> Result<String, ValidationError> {
529                match age {
530                    0..=17 => Ok("minor".to_string()),
531                    18..=64 => Ok("adult".to_string()),
532                    65..=120 => Ok("senior".to_string()),
533                    _ => Err(ValidationError::AgeError(format!("Invalid age: {}", age))),
534                }
535            },
536        )?
537        .register_global_function(
538            "validate_range",
539            |x: i64, min: i64, max: i64| -> Result<i64, ValidationError> {
540                if x < min || x > max {
541                    Err(ValidationError::RangeError { value: x, min, max })
542                } else {
543                    Ok(x)
544                }
545            },
546        )?
547        .build()?;
548
549    let test_cases = vec![
550        // Success cases
551        (
552            "safe_parse('42')",
553            "42",
554            2i64,
555            "valid@email.com",
556            true,
557            "Parse valid number",
558        ),
559        (
560            "safe_divide(10, divisor)",
561            "10",
562            2i64,
563            "test@example.com",
564            true,
565            "Safe division",
566        ),
567        (
568            "validate_email(email)",
569            "25",
570            1i64,
571            "user@domain.com",
572            true,
573            "Valid email",
574        ),
575        (
576            "validate_age(safe_parse(input))",
577            "25",
578            1i64,
579            "user@test.com",
580            true,
581            "Valid age",
582        ),
583        // Error cases
584        (
585            "safe_parse('invalid')",
586            "invalid",
587            2i64,
588            "test@test.com",
589            false,
590            "Parse invalid number",
591        ),
592        (
593            "safe_divide(10, divisor)",
594            "10",
595            0i64,
596            "test@test.com",
597            false,
598            "Division by zero",
599        ),
600        (
601            "validate_email(email)",
602            "10",
603            1i64,
604            "invalid-email",
605            false,
606            "Invalid email format",
607        ),
608        (
609            "validate_age(safe_parse(input))",
610            "150",
611            1i64,
612            "test@test.com",
613            false,
614            "Invalid age",
615        ),
616        (
617            "validate_range(safe_parse(input), 1, 100)",
618            "150",
619            2i64,
620            "test@test.com",
621            false,
622            "Value out of range",
623        ),
624    ];
625
626    for (expr, input, divisor, email, should_succeed, description) in test_cases {
627        let program = env.compile(expr)?;
628        let activation = Activation::new()
629            .bind_variable("input", input)?
630            .bind_variable("divisor", divisor)?
631            .bind_variable("email", email)?;
632
633        match program.evaluate(&activation) {
634            Ok(result) => {
635                println!("  {} = {} ✅ ({})", expr, result, description);
636                if !should_succeed {
637                    println!("    ⚠️  Expected this to fail!");
638                }
639            }
640            Err(e) => {
641                println!("  {} -> ERROR: {} ❌ ({})", expr, e, description);
642                if should_succeed {
643                    println!("    ⚠️  Expected this to succeed!");
644                }
645            }
646        }
647    }
648
649    println!();
650    Ok(())
651}
652
653/// Demo 7: Program introspection and return types
654fn demo7_program_introspection() -> Result<(), Error> {
655    println!("📌 Demo 7: Program Introspection & Return Types");
656
657    // Test with numeric expression
658    {
659        let env = Env::builder()
660            .declare_variable::<i64>("a")?
661            .declare_variable::<i64>("b")?
662            .build()?;
663        let program = env.compile("a + b")?;
664        let return_type = program.return_type();
665        println!("  Expression: 'a + b'");
666        println!("    Return type: {}", return_type);
667
668        let activation = Activation::new()
669            .bind_variable("a", 10)?
670            .bind_variable("b", 20)?;
671        let result = program.evaluate(&activation)?;
672        println!("    Result: {}", result);
673    }
674
675    // Test with string expression
676    {
677        let env = Env::builder()
678            .declare_variable::<String>("a")?
679            .declare_variable::<String>("b")?
680            .build()?;
681        let program = env.compile("a + b")?;
682        let return_type = program.return_type();
683        println!("  Expression: 'a + b' (strings)");
684        println!("    Return type: {}", return_type);
685
686        let activation = Activation::new()
687            .bind_variable("a", "Hello ".to_string())?
688            .bind_variable("b", "World!".to_string())?;
689        let result = program.evaluate(&activation)?;
690        println!("    Result: {}", result);
691    }
692
693    // Test with boolean expression
694    {
695        let env = Env::builder().declare_variable::<i64>("age")?.build()?;
696        let program = env.compile("age >= 18")?;
697        let return_type = program.return_type();
698        println!("  Expression: 'age >= 18'");
699        println!("    Return type: {}", return_type);
700
701        let activation = Activation::new().bind_variable("age", 25i64)?;
702        let result = program.evaluate(&activation)?;
703        println!("    Result: {}", result);
704    }
705
706    println!();
707    Ok(())
708}
709
710/// Demo 8: Advanced container operations and reference handling
711fn demo8_container_operations() -> Result<(), Error> {
712    println!("📌 Demo 8: Container Operations & Reference Handling");
713
714    let env = Env::builder()
715        .declare_variable::<Vec<&str>>("string_refs")?
716        .declare_variable::<HashMap<i64, &str>>("lookup_table")?
717        .declare_variable::<Option<&str>>("maybe_value")?
718        .declare_variable::<Vec<User>>("users")?
719        // Functions working with reference types
720        .register_global_function("longest_string", |strings: Vec<&str>| -> Option<String> {
721            strings
722                .iter()
723                .max_by_key(|s| s.len())
724                .map(|s| s.to_string())
725        })?
726        .register_global_function(
727            "lookup",
728            |table: HashMap<i64, &str>, key: i64| -> Option<String> {
729                table.get(&key).map(|s| s.to_string())
730            },
731        )?
732        .register_global_function("string_length", |s: Option<&str>| -> i64 {
733            s.map(|s| s.len() as i64).unwrap_or(0)
734        })?
735        // Advanced filtering and mapping
736        .register_global_function("filter_adults", |users: Vec<User>| -> Vec<User> {
737            users.into_iter().filter(|u| u.age >= 18).collect()
738        })?
739        .register_global_function(
740            "group_by_age_range",
741            |users: Vec<User>| -> HashMap<String, Vec<String>> {
742                let mut groups: HashMap<String, Vec<String>> = HashMap::new();
743                for user in users {
744                    let range = match user.age {
745                        0..=17 => "minor",
746                        18..=64 => "adult",
747                        _ => "senior",
748                    };
749                    groups.entry(range.to_string()).or_default().push(user.name);
750                }
751                groups
752            },
753        )?
754        .build()?;
755
756    // Prepare test data with proper lifetimes
757    let source_strings = [
758        "hello".to_string(),
759        "world".to_string(),
760        "rust".to_string(),
761        "programming".to_string(),
762    ];
763    let string_refs: Vec<&str> = source_strings.iter().map(|s| s.as_str()).collect();
764
765    let lookup_table: HashMap<i64, &str> = HashMap::from([(1, "one"), (2, "two"), (3, "three")]);
766
767    let maybe_value: Option<&str> = Some("test string");
768
769    let users = vec![
770        User {
771            id: 1,
772            name: "Alice".to_string(),
773            email: "alice@test.com".to_string(),
774            age: 25,
775            roles: vec![],
776            metadata: HashMap::new(),
777        },
778        User {
779            id: 2,
780            name: "Bob".to_string(),
781            email: "bob@test.com".to_string(),
782            age: 16,
783            roles: vec![],
784            metadata: HashMap::new(),
785        },
786        User {
787            id: 3,
788            name: "Carol".to_string(),
789            email: "carol@test.com".to_string(),
790            age: 67,
791            roles: vec![],
792            metadata: HashMap::new(),
793        },
794    ];
795
796    let test_expressions = vec![
797        ("longest_string(string_refs)", "Find longest string"),
798        ("lookup(lookup_table, 2)", "Lookup value by key"),
799        ("string_length(maybe_value)", "Get optional string length"),
800        ("filter_adults(users).size()", "Count adult users"),
801        (
802            "group_by_age_range(users).size()",
803            "Group users by age range",
804        ),
805    ];
806
807    let activation = Activation::new()
808        .bind_variable("string_refs", string_refs)?
809        .bind_variable("lookup_table", lookup_table)?
810        .bind_variable("maybe_value", maybe_value)?
811        .bind_variable("users", users)?;
812
813    for (expr, description) in test_expressions {
814        let program = env.compile(expr)?;
815        let result = program.evaluate(&activation)?;
816        println!("  {} = {} ({})", expr, result, description);
817    }
818
819    println!();
820    Ok(())
821}
Source§

impl<'f, Fm: FnMarker, Rm: RuntimeMarker> Env<'f, Fm, Rm>

Source

pub fn compile<S: AsRef<[u8]>>( &self, source: S, ) -> Result<Program<'f, Fm, Rm>, Error>

Compiles a CEL expression into a Program.

This method takes a CEL expression as a string or byte slice and compiles it into a Program that can be evaluated with different activations.

§Arguments
  • source - The CEL expression to compile
§Returns

Returns a Result containing the compiled Program or an Error if compilation fails.

§Examples
use cel_cxx::*;

let env = Env::builder().build().unwrap();
let program = env.compile("1 + 2 * 3").unwrap();
§Errors

Returns an error if:

  • The expression contains syntax errors
  • Referenced functions or variables are not declared
  • Type checking fails
Examples found in repository?
examples/basic.rs (line 31)
7fn main() -> Result<(), Error> {
8    println!("🚀 CEL-CXX Basic Example\n");
9
10    // Create an environment with variables and functions
11    let env = Env::builder()
12        .declare_variable::<String>("name")?
13        .declare_variable::<i64>("age")?
14        .register_global_function("greet", |name: &str| format!("Hello, {}!", name))?
15        .register_global_function("is_adult", |age: i64| age >= 18)?
16        .build()?;
17
18    // Compile and evaluate expressions
19    let expressions = vec![
20        "greet(name)",
21        "is_adult(age)",
22        "'Name: ' + name + ', Age: ' + string(age)",
23        "age >= 18 ? 'adult' : 'minor'",
24    ];
25
26    let activation = Activation::new()
27        .bind_variable("name", "Alice")?
28        .bind_variable("age", 25i64)?;
29
30    for expr in expressions {
31        let program = env.compile(expr)?;
32        let result = program.evaluate(&activation)?;
33        println!("{} = {}", expr, result);
34    }
35
36    println!("\n✅ Basic example completed!");
37    Ok(())
38}
More examples
Hide additional examples
examples/comprehensive.rs (line 200)
146fn demo1_basic_operations() -> Result<(), Error> {
147    println!("📌 Demo 1: Basic Expressions & Zero-Annotation Functions");
148
149    let env = Env::builder()
150        .declare_variable::<String>("name")?
151        .declare_variable::<i64>("age")?
152        .declare_variable::<f64>("score")?
153        // ✨ Zero-annotation functions - types automatically inferred!
154        .register_global_function("greet", |name: &str| format!("Hello, {}!", name))?
155        .register_global_function("is_adult", |age: i64| age >= 18)?
156        .register_global_function("grade", |score: f64| -> String {
157            match score {
158                90.0..=100.0 => "A".to_string(),
159                80.0..=89.9 => "B".to_string(),
160                70.0..=79.9 => "C".to_string(),
161                60.0..=69.9 => "D".to_string(),
162                _ => "F".to_string(),
163            }
164        })?
165        .register_global_function("calculate_discount", |age: i64, score: f64| -> f64 {
166            let base_discount = if age >= 65 { 0.2 } else { 0.0 };
167            let score_bonus = if score >= 90.0 { 0.1 } else { 0.0 };
168            base_discount + score_bonus
169        })?
170        .build()?;
171
172    // Test basic expressions including simple arithmetic
173    let test_cases = vec![
174        ("1 + 1", "Alice", 25i64, 95.0, "Simple arithmetic"),
175        (
176            "greet(name)",
177            "Alice",
178            25i64,
179            95.0,
180            "Function with string parameter",
181        ),
182        ("is_adult(age)", "Bob", 16i64, 85.0, "Boolean function"),
183        (
184            "grade(score)",
185            "Charlie",
186            30i64,
187            78.5,
188            "String return function",
189        ),
190        (
191            "calculate_discount(age, score)",
192            "Diana",
193            67i64,
194            92.0,
195            "Multi-parameter function",
196        ),
197    ];
198
199    for (expr, name, age, score, description) in test_cases {
200        let program = env.compile(expr)?;
201        let activation = Activation::new()
202            .bind_variable("name", name)?
203            .bind_variable("age", age)?
204            .bind_variable("score", score)?;
205
206        let result = program.evaluate(&activation)?;
207        println!("  {} = {} ({})", expr, result, description);
208    }
209
210    println!();
211    Ok(())
212}
213
214/// Demo 2: Variable binding and providers
215fn demo2_variable_operations() -> Result<(), Error> {
216    println!("📌 Demo 2: Variable Binding & Providers");
217
218    let env = Env::builder()
219        .declare_variable::<i64>("a")?
220        .declare_variable::<i64>("b")?
221        .declare_global_function::<fn() -> i64>("get_const")?
222        .register_global_function("multiply", |x: i64, y: i64| x * y)?
223        .build()?;
224
225    // Test direct variable binding
226    {
227        println!("  Variable binding:");
228        let program = env.compile("a + b")?;
229        let activation = Activation::new()
230            .bind_variable("a", 10)?
231            .bind_variable("b", 20)?;
232        let result = program.evaluate(&activation)?;
233        println!("    a + b = {} (direct binding)", result);
234    }
235
236    // Test variable provider binding
237    {
238        println!("  Variable provider binding:");
239        let program = env.compile("a * b")?;
240        let activation = Activation::new()
241            .bind_variable("a", 5)?
242            .bind_variable_provider("b", || -> Result<i64, Error> {
243                println!("    Provider called for variable 'b'");
244                Ok(7)
245            })?;
246        let result = program.evaluate(&activation)?;
247        println!("    a * b = {} (provider binding)", result);
248    }
249
250    // Test function declaration and binding
251    {
252        println!("  Function declaration & binding:");
253        let program = env.compile("get_const() + multiply(a, 3)")?;
254        let activation = Activation::new()
255            .bind_variable("a", 4)?
256            .bind_global_function("get_const", || -> Result<i64, Error> { Ok(100) })?;
257        let result = program.evaluate(&activation)?;
258        println!(
259            "    get_const() + multiply(a, 3) = {} (function binding)",
260            result
261        );
262    }
263
264    println!();
265    Ok(())
266}
267
268/// Demo 3: Opaque types with member functions
269fn demo3_opaque_member_functions() -> Result<(), Error> {
270    println!("📌 Demo 3: Opaque Types & Member Functions");
271
272    let env = Env::builder()
273        .declare_variable::<Student>("student")?
274        // ✨ Register struct methods directly using RustType::method_name syntax
275        .register_member_function("get_name", Student::get_name)?
276        .register_member_function("get_age", Student::get_age)?
277        .register_member_function("get_grade", Student::get_grade)?
278        .register_member_function("is_passing", Student::is_passing)?
279        .register_member_function("has_subject", Student::has_subject)?
280        .register_member_function("get_letter_grade", Student::get_letter_grade)?
281        .build()?;
282
283    let student = Student {
284        name: "John Doe".to_string(),
285        age: 18,
286        grade: 87.5,
287        subjects: vec!["Math".to_string(), "Physics".to_string()],
288    };
289
290    let activation = Activation::new().bind_variable("student", student)?;
291
292    let test_expressions = vec![
293        ("student.get_name()", "Get student name"),
294        ("student.get_age()", "Get student age"),
295        ("student.get_grade()", "Get numerical grade"),
296        ("student.get_letter_grade()", "Get letter grade"),
297        ("student.is_passing()", "Check if passing"),
298        ("student.has_subject('Math')", "Check if has Math subject"),
299        (
300            "student.has_subject('Chemistry')",
301            "Check if has Chemistry subject",
302        ),
303    ];
304
305    for (expr, description) in test_expressions {
306        let program = env.compile(expr)?;
307        let result = program.evaluate(&activation)?;
308        println!("  {} = {} ({})", expr, result, description);
309    }
310
311    println!();
312    Ok(())
313}
314
315/// Demo 4: Type conversions and standard Rust types
316fn demo4_type_conversions() -> Result<(), Error> {
317    println!("📌 Demo 4: Type Conversions & Standard Rust Types");
318
319    // Functions returning different types (both direct values and Results)
320    fn return_string_direct() -> String {
321        "hello world".to_string()
322    }
323    fn return_int_result() -> Result<i64, std::io::Error> {
324        Ok(42)
325    }
326    fn return_list() -> Vec<i64> {
327        vec![1, 2, 3, 4, 5]
328    }
329    fn return_map() -> HashMap<String, i64> {
330        let mut map = HashMap::new();
331        map.insert("key1".to_string(), 100);
332        map.insert("key2".to_string(), 200);
333        map
334    }
335    fn return_optional_some() -> Option<String> {
336        Some("optional value".to_string())
337    }
338    fn return_optional_none() -> Option<String> {
339        None
340    }
341
342    let env = Env::builder()
343        .register_global_function("return_string_direct", return_string_direct)?
344        .register_global_function("return_int_result", return_int_result)?
345        .register_global_function("return_list", return_list)?
346        .register_global_function("return_map", return_map)?
347        .register_global_function("return_optional_some", return_optional_some)?
348        .register_global_function("return_optional_none", return_optional_none)?
349        .build()?;
350
351    let test_cases = vec![
352        ("return_string_direct()", "String conversion"),
353        ("return_int_result()", "Result<i64> conversion"),
354        ("return_list()", "Vec<i64> conversion"),
355        ("return_map()", "HashMap conversion"),
356        ("return_optional_some()", "Option<String> Some conversion"),
357        ("return_optional_none()", "Option<String> None conversion"),
358    ];
359
360    for (expr, description) in test_cases {
361        let program = env.compile(expr)?;
362        let result = program.evaluate(())?;
363        println!("  {} = {} ({})", expr, result, description);
364
365        // Demonstrate type conversion back to Rust types
366        match expr {
367            "return_string_direct()" => {
368                let rust_string: String = result
369                    .try_into()
370                    .map_err(|_| Error::invalid_argument("string conversion failed".to_string()))?;
371                println!("    Converted back to Rust String: '{}'", rust_string);
372            }
373            "return_int_result()" => {
374                let rust_int: i64 = result
375                    .try_into()
376                    .map_err(|_| Error::invalid_argument("int conversion failed".to_string()))?;
377                println!("    Converted back to Rust i64: {}", rust_int);
378            }
379            "return_list()" => {
380                let rust_list: Vec<i64> = result
381                    .try_into()
382                    .map_err(|_| Error::invalid_argument("list conversion failed".to_string()))?;
383                println!("    Converted back to Rust Vec<i64>: {:?}", rust_list);
384            }
385            _ => {}
386        }
387    }
388
389    println!();
390    Ok(())
391}
392
393/// Demo 5: Generic functions and type annotations
394fn demo5_generic_functions() -> Result<(), Error> {
395    println!("📌 Demo 5: Generic Functions & Function Overloads");
396
397    // Generic function that counts items in any Vec<T>
398    fn count_items<T>(items: Vec<T>) -> i64 {
399        items.len() as i64
400    }
401
402    // Generic function that processes maps
403    fn get_map_size<K, V>(map: HashMap<K, V>) -> i64 {
404        map.len() as i64
405    }
406
407    // Function working with references in containers
408    fn join_strings(strings: Vec<&str>, separator: &str) -> String {
409        strings.join(separator)
410    }
411
412    let env = Env::builder()
413        .declare_variable::<Vec<String>>("string_list")?
414        .declare_variable::<Vec<i64>>("int_list")?
415        .declare_variable::<HashMap<String, i64>>("score_map")?
416        .declare_variable::<Vec<f64>>("floats")?
417        // Register generic functions with specific type annotations
418        .register_global_function("count_strings", count_items::<String>)?
419        .register_global_function("count_ints", count_items::<i64>)?
420        .register_global_function("get_string_map_size", get_map_size::<String, i64>)?
421        .register_global_function("join_strings", join_strings)?
422        // Multiple functions with same name, different signatures (overloads)
423        .register_global_function("process", |x: i64| x * 2)?
424        .register_global_function("process", |x: f64| (x * 2.0).round())?
425        .register_global_function("process", |x: String| x.to_uppercase())?
426        // Overloaded member functions for different container types
427        .register_member_function("sum", |numbers: Vec<i64>| numbers.iter().sum::<i64>())?
428        .register_member_function("sum", |floats: Vec<f64>| floats.iter().sum::<f64>())?
429        .build()?;
430
431    let test_cases = vec![
432        // Generic function tests
433        ("count_strings(string_list)", "Count strings in list"),
434        ("count_ints(int_list)", "Count integers in list"),
435        ("get_string_map_size(score_map)", "Get map size"),
436        ("join_strings(string_list, ' ')", "Join strings with space"),
437        // Function overload tests
438        ("process(42)", "Process integer (multiply by 2)"),
439        ("process(3.14)", "Process float (multiply by 2, round)"),
440        ("process('hello')", "Process string (uppercase)"),
441        ("int_list.sum()", "Sum integers"),
442        ("floats.sum()", "Sum floats"),
443    ];
444
445    let activation = Activation::new()
446        .bind_variable(
447            "string_list",
448            vec!["hello".to_string(), "world".to_string(), "rust".to_string()],
449        )?
450        .bind_variable("int_list", vec![1, 2, 3, 4, 5, 6])?
451        .bind_variable("floats", vec![1.5, 2.7, 3.143, 4.0])?
452        .bind_variable("score_map", {
453            let mut map = HashMap::new();
454            map.insert("alice".to_string(), 95);
455            map.insert("bob".to_string(), 87);
456            map.insert("charlie".to_string(), 92);
457            map
458        })?;
459
460    for (expr, description) in test_cases {
461        let program = env.compile(expr)?;
462        let result = program.evaluate(&activation)?;
463        println!("  {} = {} ({})", expr, result, description);
464    }
465
466    println!();
467    Ok(())
468}
469
470/// Demo 6: Error handling with different error types including Box<dyn std::error::Error>
471fn demo6_error_handling() -> Result<(), Error> {
472    println!("📌 Demo 6: Error Handling & Validation");
473
474    let env = Env::builder()
475        .declare_variable::<String>("input")?
476        .declare_variable::<i64>("divisor")?
477        .declare_variable::<String>("email")?
478        // Functions returning different error types using thiserror-derived types
479        .register_global_function("safe_parse", |s: &str| -> Result<i64, ValidationError> {
480            s.parse::<i64>()
481                .map_err(|e| ValidationError::ParseError(e.to_string()))
482        })?
483        .register_global_function(
484            "safe_divide",
485            |a: i64, b: i64| -> Result<f64, ValidationError> {
486                if b == 0 {
487                    Err(ValidationError::DivisionByZero)
488                } else {
489                    Ok(a as f64 / b as f64)
490                }
491            },
492        )?
493        // Additional validation functions with ValidationError
494        .register_global_function(
495            "validate_email",
496            |email: &str| -> Result<bool, ValidationError> {
497                if email.is_empty() {
498                    return Err(ValidationError::EmailError(
499                        "Email cannot be empty".to_string(),
500                    ));
501                }
502                if !email.contains('@') {
503                    return Err(ValidationError::EmailError(
504                        "Email must contain @ symbol".to_string(),
505                    ));
506                }
507                if !email.contains('.') {
508                    return Err(ValidationError::EmailError(
509                        "Email must contain . symbol".to_string(),
510                    ));
511                }
512                let parts: Vec<&str> = email.split('@').collect();
513                if parts.len() != 2 {
514                    return Err(ValidationError::EmailError(
515                        "Email must contain exactly one @ symbol".to_string(),
516                    ));
517                }
518                if parts[0].is_empty() || parts[1].is_empty() {
519                    return Err(ValidationError::EmailError(
520                        "Email local and domain parts cannot be empty".to_string(),
521                    ));
522                }
523                Ok(true)
524            },
525        )?
526        .register_global_function(
527            "validate_age",
528            |age: i64| -> Result<String, ValidationError> {
529                match age {
530                    0..=17 => Ok("minor".to_string()),
531                    18..=64 => Ok("adult".to_string()),
532                    65..=120 => Ok("senior".to_string()),
533                    _ => Err(ValidationError::AgeError(format!("Invalid age: {}", age))),
534                }
535            },
536        )?
537        .register_global_function(
538            "validate_range",
539            |x: i64, min: i64, max: i64| -> Result<i64, ValidationError> {
540                if x < min || x > max {
541                    Err(ValidationError::RangeError { value: x, min, max })
542                } else {
543                    Ok(x)
544                }
545            },
546        )?
547        .build()?;
548
549    let test_cases = vec![
550        // Success cases
551        (
552            "safe_parse('42')",
553            "42",
554            2i64,
555            "valid@email.com",
556            true,
557            "Parse valid number",
558        ),
559        (
560            "safe_divide(10, divisor)",
561            "10",
562            2i64,
563            "test@example.com",
564            true,
565            "Safe division",
566        ),
567        (
568            "validate_email(email)",
569            "25",
570            1i64,
571            "user@domain.com",
572            true,
573            "Valid email",
574        ),
575        (
576            "validate_age(safe_parse(input))",
577            "25",
578            1i64,
579            "user@test.com",
580            true,
581            "Valid age",
582        ),
583        // Error cases
584        (
585            "safe_parse('invalid')",
586            "invalid",
587            2i64,
588            "test@test.com",
589            false,
590            "Parse invalid number",
591        ),
592        (
593            "safe_divide(10, divisor)",
594            "10",
595            0i64,
596            "test@test.com",
597            false,
598            "Division by zero",
599        ),
600        (
601            "validate_email(email)",
602            "10",
603            1i64,
604            "invalid-email",
605            false,
606            "Invalid email format",
607        ),
608        (
609            "validate_age(safe_parse(input))",
610            "150",
611            1i64,
612            "test@test.com",
613            false,
614            "Invalid age",
615        ),
616        (
617            "validate_range(safe_parse(input), 1, 100)",
618            "150",
619            2i64,
620            "test@test.com",
621            false,
622            "Value out of range",
623        ),
624    ];
625
626    for (expr, input, divisor, email, should_succeed, description) in test_cases {
627        let program = env.compile(expr)?;
628        let activation = Activation::new()
629            .bind_variable("input", input)?
630            .bind_variable("divisor", divisor)?
631            .bind_variable("email", email)?;
632
633        match program.evaluate(&activation) {
634            Ok(result) => {
635                println!("  {} = {} ✅ ({})", expr, result, description);
636                if !should_succeed {
637                    println!("    ⚠️  Expected this to fail!");
638                }
639            }
640            Err(e) => {
641                println!("  {} -> ERROR: {} ❌ ({})", expr, e, description);
642                if should_succeed {
643                    println!("    ⚠️  Expected this to succeed!");
644                }
645            }
646        }
647    }
648
649    println!();
650    Ok(())
651}
652
653/// Demo 7: Program introspection and return types
654fn demo7_program_introspection() -> Result<(), Error> {
655    println!("📌 Demo 7: Program Introspection & Return Types");
656
657    // Test with numeric expression
658    {
659        let env = Env::builder()
660            .declare_variable::<i64>("a")?
661            .declare_variable::<i64>("b")?
662            .build()?;
663        let program = env.compile("a + b")?;
664        let return_type = program.return_type();
665        println!("  Expression: 'a + b'");
666        println!("    Return type: {}", return_type);
667
668        let activation = Activation::new()
669            .bind_variable("a", 10)?
670            .bind_variable("b", 20)?;
671        let result = program.evaluate(&activation)?;
672        println!("    Result: {}", result);
673    }
674
675    // Test with string expression
676    {
677        let env = Env::builder()
678            .declare_variable::<String>("a")?
679            .declare_variable::<String>("b")?
680            .build()?;
681        let program = env.compile("a + b")?;
682        let return_type = program.return_type();
683        println!("  Expression: 'a + b' (strings)");
684        println!("    Return type: {}", return_type);
685
686        let activation = Activation::new()
687            .bind_variable("a", "Hello ".to_string())?
688            .bind_variable("b", "World!".to_string())?;
689        let result = program.evaluate(&activation)?;
690        println!("    Result: {}", result);
691    }
692
693    // Test with boolean expression
694    {
695        let env = Env::builder().declare_variable::<i64>("age")?.build()?;
696        let program = env.compile("age >= 18")?;
697        let return_type = program.return_type();
698        println!("  Expression: 'age >= 18'");
699        println!("    Return type: {}", return_type);
700
701        let activation = Activation::new().bind_variable("age", 25i64)?;
702        let result = program.evaluate(&activation)?;
703        println!("    Result: {}", result);
704    }
705
706    println!();
707    Ok(())
708}
709
710/// Demo 8: Advanced container operations and reference handling
711fn demo8_container_operations() -> Result<(), Error> {
712    println!("📌 Demo 8: Container Operations & Reference Handling");
713
714    let env = Env::builder()
715        .declare_variable::<Vec<&str>>("string_refs")?
716        .declare_variable::<HashMap<i64, &str>>("lookup_table")?
717        .declare_variable::<Option<&str>>("maybe_value")?
718        .declare_variable::<Vec<User>>("users")?
719        // Functions working with reference types
720        .register_global_function("longest_string", |strings: Vec<&str>| -> Option<String> {
721            strings
722                .iter()
723                .max_by_key(|s| s.len())
724                .map(|s| s.to_string())
725        })?
726        .register_global_function(
727            "lookup",
728            |table: HashMap<i64, &str>, key: i64| -> Option<String> {
729                table.get(&key).map(|s| s.to_string())
730            },
731        )?
732        .register_global_function("string_length", |s: Option<&str>| -> i64 {
733            s.map(|s| s.len() as i64).unwrap_or(0)
734        })?
735        // Advanced filtering and mapping
736        .register_global_function("filter_adults", |users: Vec<User>| -> Vec<User> {
737            users.into_iter().filter(|u| u.age >= 18).collect()
738        })?
739        .register_global_function(
740            "group_by_age_range",
741            |users: Vec<User>| -> HashMap<String, Vec<String>> {
742                let mut groups: HashMap<String, Vec<String>> = HashMap::new();
743                for user in users {
744                    let range = match user.age {
745                        0..=17 => "minor",
746                        18..=64 => "adult",
747                        _ => "senior",
748                    };
749                    groups.entry(range.to_string()).or_default().push(user.name);
750                }
751                groups
752            },
753        )?
754        .build()?;
755
756    // Prepare test data with proper lifetimes
757    let source_strings = [
758        "hello".to_string(),
759        "world".to_string(),
760        "rust".to_string(),
761        "programming".to_string(),
762    ];
763    let string_refs: Vec<&str> = source_strings.iter().map(|s| s.as_str()).collect();
764
765    let lookup_table: HashMap<i64, &str> = HashMap::from([(1, "one"), (2, "two"), (3, "three")]);
766
767    let maybe_value: Option<&str> = Some("test string");
768
769    let users = vec![
770        User {
771            id: 1,
772            name: "Alice".to_string(),
773            email: "alice@test.com".to_string(),
774            age: 25,
775            roles: vec![],
776            metadata: HashMap::new(),
777        },
778        User {
779            id: 2,
780            name: "Bob".to_string(),
781            email: "bob@test.com".to_string(),
782            age: 16,
783            roles: vec![],
784            metadata: HashMap::new(),
785        },
786        User {
787            id: 3,
788            name: "Carol".to_string(),
789            email: "carol@test.com".to_string(),
790            age: 67,
791            roles: vec![],
792            metadata: HashMap::new(),
793        },
794    ];
795
796    let test_expressions = vec![
797        ("longest_string(string_refs)", "Find longest string"),
798        ("lookup(lookup_table, 2)", "Lookup value by key"),
799        ("string_length(maybe_value)", "Get optional string length"),
800        ("filter_adults(users).size()", "Count adult users"),
801        (
802            "group_by_age_range(users).size()",
803            "Group users by age range",
804        ),
805    ];
806
807    let activation = Activation::new()
808        .bind_variable("string_refs", string_refs)?
809        .bind_variable("lookup_table", lookup_table)?
810        .bind_variable("maybe_value", maybe_value)?
811        .bind_variable("users", users)?;
812
813    for (expr, description) in test_expressions {
814        let program = env.compile(expr)?;
815        let result = program.evaluate(&activation)?;
816        println!("  {} = {} ({})", expr, result, description);
817    }
818
819    println!();
820    Ok(())
821}
Source§

impl<'f, Rm: RuntimeMarker> Env<'f, (), Rm>

Source

pub fn force_async(self) -> Env<'f, Async, Rm>

Available on crate feature async only.

Forces conversion to an async environment.

This method converts a synchronous environment to an asynchronous one, allowing it to work with async functions and evaluation.

§Type Parameters
  • Rt - The async runtime type to use
§Examples
use cel_cxx::*;

let sync_env = Env::builder().build()?;
let async_env = sync_env.force_async();
Source§

impl<'f, Fm: FnMarker> Env<'f, Fm, ()>

Source

pub fn use_runtime<Rt: Runtime>(self) -> Env<'f, Fm, Rt>

Available on crate feature async only.

Sets the async runtime for this environment.

This method specifies which async runtime should be used for asynchronous evaluation of expressions.

§Type Parameters
  • Rt - The runtime type to use (must implement Runtime)
§Examples
use cel_cxx::*;

let env = Env::builder()
    .build()?
    .use_runtime::<Tokio>();
Source

pub fn use_tokio(self) -> Env<'f, Fm, Tokio>

Available on crate features async and tokio only.

Configures the environment to use the Tokio async runtime.

This is a convenience method for setting the runtime to Tokio. Requires the tokio feature to be enabled.

§Examples
use cel_cxx::*;

let env = Env::builder()
    .build()?
    .use_tokio();
Source

pub fn use_async_std(self) -> Env<'f, Fm, AsyncStd>

Available on crate features async and async-std only.

Configures the environment to use the async-std runtime.

This is a convenience method for setting the runtime to async-std. Requires the async-std feature to be enabled.

§Examples
use cel_cxx::*;

let env = Env::builder()
    .build()?
    .use_async_std();
Source

pub fn use_smol(self) -> Env<'f, Fm, Smol>

Available on crate features async and smol only.

Configures the environment to use the smol runtime.

This is a convenience method for setting the runtime to smol. Requires the smol feature to be enabled.

§Examples
use cel_cxx::*;

let env = Env::builder().use_smol();

Trait Implementations§

Source§

impl<'f, Fm: FnMarker, Rm: RuntimeMarker> Clone for Env<'f, Fm, Rm>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'f, Fm: FnMarker, Rm: RuntimeMarker> Debug for Env<'f, Fm, Rm>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'f, Fm, Rm> Freeze for Env<'f, Fm, Rm>

§

impl<'f, Fm = (), Rm = ()> !RefUnwindSafe for Env<'f, Fm, Rm>

§

impl<'f, Fm, Rm> Send for Env<'f, Fm, Rm>
where Fm: Send, Rm: Send,

§

impl<'f, Fm, Rm> Sync for Env<'f, Fm, Rm>
where Fm: Sync, Rm: Sync,

§

impl<'f, Fm, Rm> Unpin for Env<'f, Fm, Rm>
where Fm: Unpin, Rm: Unpin,

§

impl<'f, Fm = (), Rm = ()> !UnwindSafe for Env<'f, Fm, Rm>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more