cel_cxx/function/mod.rs
1//! Function registration and implementation utilities.
2//!
3//! The function system provides a flexible way to register and call functions in CEL expressions.
4//! Functions can be either compile-time declarations (type signatures only) or runtime
5//! implementations (callable code).
6//!
7//! # Key Components
8//!
9//! - [`FunctionRegistry`]: Compile-time function registry for declaring function signatures and registering implementations
10//! - [`FunctionBindings`]: Runtime function bindings for calling functions during evaluation
11//! - [`FunctionOverloads`]: Function overload management supporting multiple implementations with different signatures
12//! - **Declarations**: Use [`FunctionDecl`] trait for compile-time type checking
13//! - **Implementations**: Use [`IntoFunction`] trait for runtime function calls
14//!
15//! # Examples
16//!
17//! ```rust,no_run
18//! use cel_cxx::*;
19//!
20//! // Register a function implementation
21//! let mut env = Env::builder()
22//! .register_global_function("greet", |name: String| -> String {
23//! format!("Hello, {}!", name)
24//! })?
25//! .build()?;
26//! # Ok::<(), cel_cxx::Error>(())
27//! ```
28//!
29//! # Detailed Documentation
30//!
31//! Zero-annotation function registration for CEL expression evaluation.
32//!
33//! This module provides a type-safe, zero-annotation function registration system
34//! that allows Rust functions to be called from CEL expressions without manual
35//! type annotations or wrapper code.
36//!
37//! # Two Function Systems
38//!
39//! This module provides two distinct but complementary function systems:
40//!
41//! ## 1. Function Registration (Runtime Implementation)
42//! - **Purpose**: Register actual callable Rust functions/closures
43//! - **Entry point**: [`IntoFunction`] trait and registration methods
44//! - **Usage**: `env.register_function("name", function_impl)`
45//! - **Provides**: Executable code that can be called during expression evaluation
46//!
47//! ## 2. Function Declaration (Compile-Time Signatures)
48//! - **Purpose**: Declare function signatures for type checking without implementation
49//! - **Entry point**: [`FunctionDecl`] trait and declaration methods
50//! - **Usage**: `env.declare_function::<SignatureType>("name")`
51//! - **Provides**: Type information for compile-time validation and overload resolution
52//!
53//! These systems work together: you can declare functions for type checking during
54//! development, then provide implementations later, or register complete functions
55//! that include both signature and implementation.
56//!
57//! # Features
58//!
59//! - **Zero-annotation registration**: Functions can be registered without explicit type annotations
60//! - **Lifetime-aware closures**: Support for closures that capture environment variables
61//! - **Reference return types**: Safe handling of functions returning borrowed data like `&str`
62//! - **Unified error handling**: Automatic conversion of `Result<T, E>` return types
63//! - **Async function support**: Optional support for async functions (requires `async` feature)
64//! - **Thread safety**: All function implementations are `Send + Sync`
65//!
66//! # How Zero-Annotation Works
67//!
68//! The zero-annotation system is built on top of Rust's type system and Generic Associated Types (GATs).
69//! When you register a function, the system automatically:
70//!
71//! 1. **Extracts argument types** from the function signature using [`FunctionDecl`]
72//! 2. **Infers return types** using the [`IntoResult`] trait
73//! 3. **Generates type-safe converters** that handle lifetime erasure safely
74//! 4. **Creates a unified interface** through the [`Function`] struct
75//!
76//! ## Type Conversion Process
77//!
78//! For each argument type `T`, the system:
79//! - Uses `T: FromValue + TypedValue` to convert from CEL values
80//! - Leverages GATs (`FromValue::Output<'a>`) to handle borrowed data like `&str`
81//! - Safely handles lifetime relationships through internal conversion mechanisms
82//!
83//! ## Safety Guarantees
84//!
85//! The lifetime handling is safe because:
86//! - Source CEL values remain valid for the entire function call
87//! - Converted arguments are immediately consumed by the target function
88//! - No references escape the function call scope
89//!
90//! # Examples
91//!
92//! ## Basic function registration
93//!
94//! ```rust,no_run
95//! use cel_cxx::{function::IntoFunction, Error};
96//!
97//! // Simple function
98//! fn add(a: i64, b: i64) -> i64 {
99//! a + b
100//! }
101//! let func = add.into_function();
102//!
103//! // Function with error handling
104//! fn divide(a: i64, b: i64) -> Result<i64, Error> {
105//! if b == 0 {
106//! Err(Error::invalid_argument("division by zero"))
107//! } else {
108//! Ok(a / b)
109//! }
110//! }
111//! let func = divide.into_function();
112//! ```
113//!
114//! ## Advanced: Reference return types
115//!
116//! The system handles functions that return borrowed data:
117//!
118//! ```rust,no_run
119//! use cel_cxx::function::*;
120//! // Function returning borrowed data
121//! fn get_first(items: Vec<&str>) -> &str {
122//! items.first().map_or("", |s| *s)
123//! }
124//! let func = get_first.into_function();
125//!
126//! // The system automatically handles the lifetime relationships
127//! ```
128//!
129//! ## Closure registration
130//!
131//! ```rust,no_run
132//! use cel_cxx::function::*;
133//! // Capturing closure
134//! let multiplier = 3;
135//! let multiply = move |x: i64| -> i64 { x * multiplier };
136//! let func = multiply.into_function();
137//!
138//! // String processing closure
139//! let prefix = String::from("Hello, ");
140//! let with_prefix = move |name: &str| -> String {
141//! format!("{}{}", prefix, name)
142//! };
143//! let func = with_prefix.into_function();
144//! ```
145//!
146//! ## Function metadata and invocation
147//!
148//! ```rust,no_run
149//! use cel_cxx::function::*;
150//! fn add(a: i64, b: i64) -> i64 { a + b }
151//! let func = add.into_function();
152//!
153//! // Get function metadata
154//! let arg_types = func.arguments(); // Vec<ValueType>
155//! let return_type = func.result(); // ValueType
156//!
157//! // Call the function (would need proper Value instances in real code)
158//! // let args = vec![Value::from(10i64), Value::from(20i64)];
159//! // let result = func.call(args);
160//! ```
161//!
162//! # Async Functions
163//!
164//! When the `async` feature is enabled, you can register async functions:
165//!
166//! ```rust,no_run
167//! # use cel_cxx::function::*;
168//! # #[cfg(feature = "tokio")]
169//! # async fn example() {
170//! // Async function
171//! async fn fetch_data(url: String) -> String {
172//! // Simulate async work
173//! tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
174//! format!("Data from {}", url)
175//! }
176//!
177//! let func = fetch_data.into_function();
178//! // func.call() returns a Future that can be awaited
179//! # }
180//! ```
181
182use crate::error::*;
183use crate::marker::*;
184use crate::maybe_future::*;
185use crate::types::*;
186use crate::values::*;
187use std::sync::Arc;
188
189pub mod decl;
190pub use decl::*;
191
192pub mod overload;
193pub use overload::*;
194
195mod registry;
196pub use registry::*;
197
198mod bindings;
199pub use bindings::*;
200
201/// Marker trait for function argument tuples.
202///
203/// This trait is automatically implemented for tuples of types that implement
204/// [`FromValue`] and [`TypedValue`]. It serves as a constraint to ensure
205/// type safety in function registration.
206///
207/// The trait supports function signatures with 0 to 10 parameters. Each parameter
208/// type must be convertible from CEL values and have a known CEL type.
209///
210/// # Implementation Details
211///
212/// This trait is sealed and cannot be implemented outside this crate. It is
213/// automatically implemented for valid argument tuple types through procedural
214/// macros.
215///
216/// # Supported Argument Types
217///
218/// Any type that implements both [`FromValue`] and [`TypedValue`] can be used
219/// as a function argument. This includes:
220///
221/// - **Primitive types**: `bool`, `i64`, `u64`, `f64`, `String`, `Vec<u8>`
222/// - **Reference types**: `&str`, `&[u8]` (with proper lifetime handling)
223/// - **Collection types**: `Vec<T>`, `HashMap<K, V>` where `T`, `K`, `V` are valid CEL types
224/// - **Custom types**: Types that implement the required traits
225///
226/// # Note
227///
228/// This trait is sealed and cannot be implemented outside this crate.
229/// It supports function signatures with 0 to 10 parameters.
230pub trait Arguments: Sized + private::Sealed {
231 /// The number of arguments in the argument tuple.
232 ///
233 /// This constant provides compile-time information about the arity
234 /// (number of parameters) of a function signature.
235 ///
236 /// # Examples
237 ///
238 /// - `()` has `LEN = 0`
239 /// - `(String)` has `LEN = 1`
240 /// - `(i64, i64)` has `LEN = 2`
241 const LEN: usize;
242}
243
244/// Marker trait for function argument tuples with at least one parameter.
245///
246/// This trait extends [`Arguments`] to identify function signatures that have
247/// at least one argument. It is used to restrict member function registration
248/// to ensure that member functions always have a receiver object as their first
249/// parameter.
250///
251/// # Purpose
252///
253/// Member functions in CEL must have at least one argument (the receiver object).
254/// This trait provides compile-time type checking to enforce this constraint
255/// when registering member functions through [`FunctionRegistry::register_member`].
256///
257/// # Implementation Details
258///
259/// This trait is automatically implemented for all non-empty argument tuples
260/// (1 to 10 parameters) through the [`impl_arguments!`] macro. The empty tuple
261/// `()` implements [`Arguments`] but does not implement `NonEmptyArguments`,
262/// which allows the type system to distinguish between zero-argument and
263/// non-zero-argument functions.
264///
265/// # Usage in Member Functions
266///
267/// When registering a member function, the type system requires:
268/// ```rust,ignore
269/// Args: Arguments + NonEmptyArguments
270/// ```
271///
272/// This constraint ensures that:
273/// - Member functions cannot be registered with zero arguments
274/// - The first argument of a member function represents the receiver object
275/// - Type safety is enforced at compile time
276///
277/// # Examples
278///
279/// Valid member function signatures (implement `NonEmptyArguments`):
280/// - `(String)` - one argument
281/// - `(String, i64)` - two arguments
282/// - `(Vec<i64>, bool)` - two arguments
283///
284/// Invalid member function signature (does not implement `NonEmptyArguments`):
285/// - `()` - zero arguments (cannot be used for member functions)
286///
287/// # Note
288///
289/// This trait is sealed and cannot be implemented outside this crate.
290/// It is automatically implemented for argument tuples with 1 to 10 parameters.
291pub trait NonEmptyArguments: Arguments + private::Sealed {}
292
293/// Trait for types that can be converted into function implementations.
294///
295/// This is the main entry point for function registration. Any Rust function
296/// or closure that meets the constraints can be converted into a [`Function`].
297///
298/// # Type System Integration
299///
300/// The trait uses Rust's type system to automatically:
301/// - Extract function signatures using [`FunctionDecl`]
302/// - Handle argument conversion using [`FromValue`] with GATs
303/// - Manage return type conversion using [`IntoResult`]
304/// - Support both synchronous and asynchronous functions
305///
306/// # Generic Associated Types (GATs)
307///
308/// This trait leverages GATs to handle complex lifetime relationships:
309/// - Functions returning `&str` can borrow from input parameters
310/// - Closures can capture environment variables with appropriate lifetimes
311/// - The system maintains memory safety through controlled lifetime erasure
312///
313/// # Note
314///
315/// This trait is sealed and cannot be implemented outside this crate.
316///
317/// # Type Parameters
318///
319/// - `'f`: Lifetime parameter for captured data in closures
320/// - `Fm`: Function marker (sync/async)
321/// - `Args`: Argument tuple type
322///
323/// # Examples
324///
325/// ## Simple Functions
326///
327/// ```rust
328/// # use cel_cxx::function::IntoFunction;
329/// # use std::convert::Infallible;
330/// fn add(a: i64, b: i64) -> i64 { a + b }
331/// fn divide(a: i64, b: i64) -> Result<f64, Infallible> {
332/// Ok(a as f64 / b as f64)
333/// }
334///
335/// let add_func = add.into_function();
336/// let div_func = divide.into_function();
337/// ```
338///
339/// ## Closures with Captured Variables
340///
341/// ```rust
342/// # use cel_cxx::function::IntoFunction;
343/// let factor = 2.5;
344/// let scale = move |x: f64| -> f64 { x * factor };
345/// let scale_func = scale.into_function();
346/// ```
347///
348/// ## Functions with Reference Parameters
349///
350/// ```rust
351/// # use cel_cxx::function::IntoFunction;
352/// fn process_text(text: &str, uppercase: bool) -> String {
353/// if uppercase { text.to_uppercase() } else { text.to_lowercase() }
354/// }
355/// let process_func = process_text.into_function();
356/// ```
357pub trait IntoFunction<'f, Fm: FnMarker, Args = ()>: private::Sealed<Fm, Args> {
358 /// Convert this function into a type-erased implementation.
359 ///
360 /// This method performs the conversion from a strongly-typed Rust function
361 /// to a type-erased [`Function`] that can be called from CEL expressions.
362 ///
363 /// # Returns
364 ///
365 /// A [`Function`] that encapsulates the original function with:
366 /// - Type-safe argument conversion
367 /// - Return value conversion
368 /// - Error handling
369 /// - Async support (if applicable)
370 ///
371 /// # Performance
372 ///
373 /// The conversion is zero-cost at runtime. All type checking and conversion
374 /// logic is generated at compile time.
375 fn into_function(self) -> Function<'f>;
376}
377
378/// A type-erased function implementation that can be called from CEL expressions.
379///
380/// This is the main type used to store and invoke registered functions.
381/// It provides a uniform interface for calling functions regardless of
382/// their original signature.
383///
384/// # Design
385///
386/// The `Function` struct uses dynamic dispatch through trait objects to provide
387/// a uniform interface while maintaining type safety. The original function's
388/// type information is preserved through internal trait implementations.
389///
390/// # Memory Safety
391///
392/// Despite using type erasure, the system maintains complete memory safety:
393/// - All conversions are checked at runtime
394/// - Lifetime relationships are preserved where possible
395/// - Reference parameters are handled safely through controlled lifetime management
396///
397/// # Performance
398///
399/// - Function calls involve minimal overhead (one virtual call + conversions)
400/// - Argument validation is performed once per call
401/// - Type conversions use zero-copy where possible
402///
403/// # Examples
404///
405/// ## Basic Usage
406///
407/// ```rust
408/// # use cel_cxx::function::*;
409/// fn greet(name: &str) -> String {
410/// format!("Hello, {}!", name)
411/// }
412///
413/// let func = greet.into_function();
414/// let args = vec!["World".into()];
415/// let result = func.call(args);
416/// ```
417///
418/// ## Metadata Inspection
419///
420/// ```rust
421/// # use cel_cxx::function::*;
422/// # fn greet(name: &str) -> String { format!("Hello, {}!", name) }
423/// let func = greet.into_function();
424///
425/// // Inspect function signature
426/// println!("Arguments: {:?}", func.arguments());
427/// println!("Return type: {:?}", func.result());
428/// println!("Function type: {:?}", func.function_type());
429/// ```
430#[derive(Debug, Clone)]
431pub struct Function<'f> {
432 inner: Arc<dyn ErasedFn + 'f>,
433}
434
435impl<'f> Function<'f> {
436 /// Create a new function implementation from an `ErasedFn`.
437 fn new(inner: impl ErasedFn + 'f) -> Self {
438 Self {
439 inner: Arc::new(inner),
440 }
441 }
442
443 /// Call the function with the provided arguments.
444 ///
445 /// This method invokes the function with type-safe argument conversion
446 /// and return value handling. It supports both synchronous and asynchronous
447 /// functions through the [`MaybeFuture`] return type.
448 ///
449 /// # Arguments
450 ///
451 /// * `args` - Vector of [`Value`] arguments to pass to the function
452 ///
453 /// # Returns
454 ///
455 /// Returns a [`MaybeFuture`] that represents either an immediate result or a future:
456 ///
457 /// - **Without `async` feature**: [`MaybeFuture`] is `Result<Value, Error>` - returns immediately
458 /// - **With `async` feature**: [`MaybeFuture`] can be either:
459 /// - `MaybeFuture::Result(Result<Value, Error>)` for synchronous functions
460 /// - `MaybeFuture::Future(BoxFuture<Result<Value, Error>>)` for async functions
461 ///
462 /// # Type Safety
463 ///
464 /// The method performs runtime type checking to ensure:
465 /// - Correct number of arguments is provided
466 /// - Each argument can be converted to the expected parameter type
467 /// - Return value conversion succeeds
468 ///
469 /// # Errors
470 ///
471 /// Returns an [`Error`] if:
472 /// - The number of arguments doesn't match the function signature
473 /// - Argument types cannot be converted to the expected types
474 /// - The function itself returns an error
475 /// - Return value conversion fails
476 ///
477 /// # Examples
478 ///
479 /// ## Synchronous function call
480 ///
481 /// ```rust
482 /// # use cel_cxx::function::*;
483 /// # use cel_cxx::values::Value;
484 /// fn add(a: i64, b: i64) -> i64 { a + b }
485 /// let func = add.into_function();
486 ///
487 /// let args = vec![Value::Int(10), Value::Int(20)];
488 /// let maybe_result = func.call(args);
489 ///
490 /// // In sync mode, extract the result directly
491 /// # #[cfg(not(feature = "async"))]
492 /// let result = maybe_result.unwrap();
493 ///
494 /// // In async mode, check if it's an immediate result
495 /// # #[cfg(feature = "async")]
496 /// let result = maybe_result.expect_result("shoud be result")?;
497 ///
498 /// assert_eq!(result, Value::Int(30));
499 /// # Ok::<(), cel_cxx::Error>(())
500 /// ```
501 ///
502 /// ## Async function call (when `async` feature is enabled)
503 ///
504 /// ```rust
505 /// # #[cfg(feature = "async")]
506 /// # async fn example() {
507 /// # use cel_cxx::function::*;
508 /// # use cel_cxx::values::Value;
509 /// async fn async_multiply(a: i64, b: i64) -> i64 { a * b }
510 /// let func = async_multiply.into_function();
511 ///
512 /// let args = vec![Value::Int(6), Value::Int(7)];
513 /// let maybe_result = func.call(args);
514 ///
515 /// // For async functions, extract and await the future
516 /// let result = maybe_result.unwrap_future().await.unwrap();
517 /// assert_eq!(result, Value::Int(42));
518 /// # }
519 /// ```
520 pub fn call<'this, 'future>(&'this self, args: Vec<Value>) -> MaybeFuture<'future, Value, Error>
521 where
522 'this: 'future,
523 Self: 'future,
524 {
525 self.inner.call(args)
526 }
527
528 /// Get the expected argument types for this function.
529 ///
530 /// Returns the function signature information that can be used for:
531 /// - Compile-time type checking
532 /// - Runtime argument validation
533 /// - Documentation generation
534 /// - IDE support and auto-completion
535 ///
536 /// # Returns
537 ///
538 /// A vector of [`ValueType`] representing the expected argument types
539 /// in the order they should be provided to [`call`](Self::call).
540 ///
541 /// # Examples
542 ///
543 /// ```rust
544 /// # use cel_cxx::function::*;
545 /// # use cel_cxx::types::ValueType;
546 /// fn process(name: &str, count: i64, active: bool) -> String {
547 /// format!("{}: {} ({})", name, count, active)
548 /// }
549 /// let func = process.into_function();
550 ///
551 /// let arg_types = func.arguments();
552 /// assert_eq!(arg_types, vec![
553 /// ValueType::String,
554 /// ValueType::Int,
555 /// ValueType::Bool
556 /// ]);
557 /// ```
558 pub fn arguments(&self) -> Vec<ValueType> {
559 self.inner.arguments()
560 }
561
562 /// Get the return type of this function.
563 ///
564 /// Returns type information that can be used for:
565 /// - Compile-time type checking of expressions
566 /// - Runtime result validation
567 /// - Type inference in complex expressions
568 ///
569 /// # Returns
570 ///
571 /// The [`ValueType`] that this function returns when called successfully.
572 /// For functions returning `Result<T, E>`, this returns the success type `T`.
573 ///
574 /// # Examples
575 ///
576 /// ```rust
577 /// # use cel_cxx::function::*;
578 /// # use cel_cxx::types::ValueType;
579 /// fn calculate(x: f64, y: f64) -> f64 { x * y + 1.0 }
580 /// let func = calculate.into_function();
581 ///
582 /// assert_eq!(func.result(), ValueType::Double);
583 /// ```
584 ///
585 /// ```rust
586 /// # use cel_cxx::function::*;
587 /// # use cel_cxx::types::ValueType;
588 /// # use std::convert::Infallible;
589 /// fn get_message() -> Result<String, Infallible> {
590 /// Ok("Hello".to_string())
591 /// }
592 /// let func = get_message.into_function();
593 ///
594 /// // Returns the success type, not Result<String, Infallible>
595 /// assert_eq!(func.result(), ValueType::String);
596 /// ```
597 pub fn result(&self) -> ValueType {
598 self.inner.result()
599 }
600
601 /// Get complete function type information.
602 ///
603 /// Returns a [`FunctionType`] that combines argument and return type information.
604 /// This is useful for:
605 /// - Function signature matching
606 /// - Overload resolution
607 /// - Type checking in complex expressions
608 ///
609 /// # Returns
610 ///
611 /// A [`FunctionType`] containing complete function signature information.
612 ///
613 /// # Examples
614 ///
615 /// ```rust
616 /// # use cel_cxx::function::*;
617 /// # use cel_cxx::types::{ValueType, FunctionType};
618 /// fn multiply(a: i64, b: i64) -> i64 { a * b }
619 /// let func = multiply.into_function();
620 ///
621 /// let func_type = func.function_type();
622 /// assert_eq!(func_type.arguments(), &[ValueType::Int, ValueType::Int]);
623 /// assert_eq!(func_type.result(), &ValueType::Int);
624 /// ```
625 pub fn function_type(&self) -> FunctionType {
626 FunctionType::new(self.result(), self.arguments())
627 }
628
629 /// Get the number of arguments this function expects.
630 ///
631 /// This is a convenience method equivalent to `self.arguments().len()`.
632 /// Useful for quick arity checking without allocating the full argument
633 /// type vector.
634 ///
635 /// # Returns
636 ///
637 /// The number of parameters this function expects.
638 ///
639 /// # Examples
640 ///
641 /// ```rust
642 /// # use cel_cxx::function::*;
643 /// fn no_args() -> i64 { 42 }
644 /// fn one_arg(x: i64) -> i64 { x }
645 /// fn three_args(a: i64, b: i64, c: i64) -> i64 { a + b + c }
646 ///
647 /// assert_eq!(no_args.into_function().arguments_len(), 0);
648 /// assert_eq!(one_arg.into_function().arguments_len(), 1);
649 /// assert_eq!(three_args.into_function().arguments_len(), 3);
650 /// ```
651 pub fn arguments_len(&self) -> usize {
652 self.inner.arguments_len()
653 }
654}
655
656// =============================================================================
657// Implementation details
658// =============================================================================
659
660/// Internal trait for type-erased function implementations.
661///
662/// This trait provides a uniform interface for calling functions regardless
663/// of their original signature. It is not exposed publicly as users should
664/// interact with [`Function`] instead.
665trait ErasedFn: Send + Sync {
666 /// Call the function with the provided arguments.
667 fn call<'this, 'future>(&'this self, args: Vec<Value>) -> MaybeFuture<'future, Value, Error>
668 where
669 'this: 'future,
670 Self: 'future;
671
672 /// Get the expected argument types.
673 fn arguments(&self) -> Vec<ValueType>;
674
675 /// Get the return type.
676 fn result(&self) -> ValueType;
677
678 /// Get the number of expected arguments.
679 fn arguments_len(&self) -> usize;
680}
681
682macro_rules! impl_arguments {
683 () => {
684 impl Arguments for () {
685 const LEN: usize = 0;
686 }
687 impl private::Sealed for () {}
688 };
689 (
690 $($ty:ident),+
691 ) => {
692 impl<$($ty: FromValue + TypedValue),+> Arguments for ($($ty,)*) {
693 const LEN: usize = count_args!($($ty),*) as usize;
694 }
695 impl<$($ty: FromValue + TypedValue),+> NonEmptyArguments for ($($ty,)*) {}
696 impl<$($ty: FromValue + TypedValue),+> private::Sealed for ($($ty,)*) {}
697 }
698}
699
700impl_arguments!();
701impl_arguments!(A1);
702impl_arguments!(A1, A2);
703impl_arguments!(A1, A2, A3);
704impl_arguments!(A1, A2, A3, A4);
705impl_arguments!(A1, A2, A3, A4, A5);
706impl_arguments!(A1, A2, A3, A4, A5, A6);
707impl_arguments!(A1, A2, A3, A4, A5, A6, A7);
708impl_arguments!(A1, A2, A3, A4, A5, A6, A7, A8);
709impl_arguments!(A1, A2, A3, A4, A5, A6, A7, A8, A9);
710impl_arguments!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
711
712/// Internal trait for safely converting `FromValue::Output` to function parameter types.
713///
714/// This trait contains unsafe code for lifetime erasure and should only be used
715/// within the controlled context of function dispatch. It is not exposed publicly
716/// to ensure memory safety.
717trait Argument: FromValue + TypedValue {
718 /// Convert a CEL value to the function parameter type.
719 ///
720 /// This method safely converts a [`Value`] reference to the target type
721 /// by first using [`FromValue::from_value`] and then performing controlled
722 /// lifetime erasure via [`Self::from_output`].
723 fn make_argument(value: &Value) -> Result<Self, FromValueError> {
724 let output = <Self as FromValue>::from_value(value)?;
725 Ok(unsafe { Self::from_output(output) })
726 }
727
728 /// Convert `FromValue::Output<'a>` to `Self` by erasing lifetime information.
729 ///
730 /// # Safety
731 ///
732 /// This method performs an unsafe lifetime erasure operation that is only safe
733 /// under specific controlled conditions:
734 ///
735 /// 1. **Memory Layout Guarantee**: The method assumes that `Self` and
736 /// `Self::Output<'a>` have identical memory layouts. This is verified by
737 /// a debug assertion checking `size_of` equality.
738 ///
739 /// 2. **Lifetime Erasure Safety**: The lifetime parameter 'a is erased through
740 /// unsafe pointer casting. This is safe because:
741 /// - The input `output` is consumed (moved) into this function
742 /// - The returned `Self` will be immediately consumed by the function call
743 /// - No references escape the function call scope
744 ///
745 /// 3. **Controlled Usage Context**: This method is only called within the
746 /// function dispatch mechanism where:
747 /// - The source `&[Value]` array remains valid for the entire function call
748 /// - The converted arguments are immediately passed to the target function
749 /// - The function result is immediately converted via `IntoResult`
750 ///
751 /// 4. **Type System Cooperation**: For reference types like `&str`:
752 /// - `Self::Output<'a>` is `&'a str` (borrowed from Value)
753 /// - `Self` is `&str` (with erased lifetime)
754 /// - The underlying string data in Value remains valid throughout the call
755 ///
756 /// The safety of this operation relies on the fact that the lifetime erasure
757 /// is temporary and scoped - the converted values never outlive the original
758 /// Value array that owns the underlying data.
759 ///
760 /// # Implementation Details
761 ///
762 /// The conversion process:
763 /// 1. Cast the reference to `output` as a pointer to `Self`
764 /// 2. Forget the original `output` to prevent double-drop
765 /// 3. Read the value from the pointer, effectively transferring ownership
766 ///
767 /// This is essentially a controlled `transmute` operation that preserves
768 /// the bit representation while changing the type signature.
769 unsafe fn from_output<'a>(output: <Self as FromValue>::Output<'a>) -> Self {
770 debug_assert!(
771 std::mem::size_of::<<Self as FromValue>::Output<'a>>() == std::mem::size_of::<Self>()
772 );
773
774 let ptr: *const Self = (&output as *const <Self as FromValue>::Output<'a>).cast();
775 std::mem::forget(output);
776 std::ptr::read(ptr)
777 }
778}
779
780// Blanket implementation for all types that implement FromValue and TypedValue
781impl<T: FromValue + TypedValue> Argument for T {}
782
783/// Internal wrapper for synchronous functions that implements [`ErasedFn`].
784///
785/// This struct wraps a function along with phantom data for its signature,
786/// allowing type-erased storage and invocation.
787struct FnWrapper<F, R, Args> {
788 func: F,
789 _phantom: std::marker::PhantomData<(R, Args)>,
790}
791
792impl<F, R, Args> FnWrapper<F, R, Args> {
793 /// Create a new function wrapper.
794 fn new(func: F) -> Self {
795 Self {
796 func,
797 _phantom: std::marker::PhantomData,
798 }
799 }
800}
801
802// =============================================================================
803// Helper macros and implementations
804// =============================================================================
805
806/// Compile-time macro to count the number of function arguments.
807macro_rules! count_args {
808 () => { 0 };
809 ($head:ident $(, $tail:ident)*) => { 1 + count_args!($($tail),*) };
810}
811use count_args;
812
813/// Macro to generate [`ErasedFn`] implementations for synchronous functions
814/// with different arities (0 to 10 parameters).
815macro_rules! impl_fn_wrapper {
816 ($($ty:ident),*) => {
817 paste::paste! {
818 impl<F, R, $($ty,)*> ErasedFn for FnWrapper<F, R, ($($ty,)*)>
819 where
820 F: Fn($($ty,)*) -> R + Send + Sync,
821 R: IntoResult + Send + Sync,
822 $($ty: FromValue + TypedValue + Send + Sync,)*
823 {
824 fn call<'this, 'future>(
825 &'this self,
826 args: Vec<Value>
827 ) -> MaybeFuture<'future, Value, Error>
828 where 'this: 'future, Self: 'future {
829 let f = || {
830 // Compile-time constant: number of expected arguments
831 const EXPECTED_LEN: usize = count_args!($($ty),*);
832
833 if args.len() != EXPECTED_LEN {
834 return Err(Error::invalid_argument(
835 format!("expected {} arguments, got {}", EXPECTED_LEN, args.len())
836 ));
837 }
838
839 #[allow(unused_mut, unused_variables)]
840 let mut iter = args.iter();
841 $(
842 let [< $ty:lower >] = $ty::make_argument(
843 iter.next().expect("argument count already validated")
844 ).map_err(|e| Error::invalid_argument(format!("argument error: {}", e)))?;
845 )*
846
847 let result = (self.func)($([< $ty:lower >],)*);
848 result.into_result()
849 };
850 f().into()
851 }
852
853 fn arguments(&self) -> Vec<ValueType> {
854 vec![$($ty::value_type()),*]
855 }
856
857 fn result(&self) -> ValueType {
858 R::value_type()
859 }
860
861 fn arguments_len(&self) -> usize {
862 count_args!($($ty),*)
863 }
864 }
865
866 // Implementation of IntoFunction for synchronous functions
867 impl<'f, F, R, $($ty,)*> IntoFunction<'f, (), ($($ty,)*)> for F
868 where
869 F: Fn($($ty,)*) -> R + Send + Sync + 'f,
870 R: IntoResult + Send + Sync + 'f,
871 ($($ty,)*): Arguments,
872 $($ty: FromValue + TypedValue + Send + Sync + 'f,)*
873 {
874 fn into_function(self) -> Function<'f> {
875 Function::new(FnWrapper::<F, R, ($($ty,)*)>::new(self))
876 }
877 }
878
879 // Sealed implementation for synchronous functions
880 impl<'f, F, R, $($ty,)*> private::Sealed<(), ($($ty,)*)> for F
881 where
882 F: Fn($($ty,)*) -> R + Send + Sync + 'f,
883 R: IntoResult + Send + Sync + 'f,
884 ($($ty,)*): Arguments,
885 $($ty: FromValue + TypedValue + Send + Sync + 'f,)*
886 {}
887 }
888 };
889}
890
891// Generate implementations for functions with 0-10 parameters
892impl_fn_wrapper!();
893impl_fn_wrapper!(A1);
894impl_fn_wrapper!(A1, A2);
895impl_fn_wrapper!(A1, A2, A3);
896impl_fn_wrapper!(A1, A2, A3, A4);
897impl_fn_wrapper!(A1, A2, A3, A4, A5);
898impl_fn_wrapper!(A1, A2, A3, A4, A5, A6);
899impl_fn_wrapper!(A1, A2, A3, A4, A5, A6, A7);
900impl_fn_wrapper!(A1, A2, A3, A4, A5, A6, A7, A8);
901impl_fn_wrapper!(A1, A2, A3, A4, A5, A6, A7, A8, A9);
902impl_fn_wrapper!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
903
904// =============================================================================
905// Async function support (optional feature)
906// =============================================================================
907
908/// Internal wrapper for asynchronous functions that implements [`ErasedFn`].
909///
910/// This struct is similar to [`FnWrapper`] but designed for async functions
911/// that return futures. It's only available when the `async` feature is enabled.
912#[cfg(feature = "async")]
913#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
914struct FnWrapperAsync<F, R, Args> {
915 func: F,
916 _phantom: std::marker::PhantomData<(R, Args)>,
917}
918
919#[cfg(feature = "async")]
920#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
921impl<F, R, Args> FnWrapperAsync<F, R, Args> {
922 /// Create a new async function wrapper.
923 fn new(func: F) -> Self {
924 Self {
925 func,
926 _phantom: std::marker::PhantomData,
927 }
928 }
929}
930
931#[cfg(feature = "async")]
932#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
933mod async_impls {
934 use super::*;
935
936 /// Macro to generate [`ErasedFn`] implementations for asynchronous functions
937 /// with different arities (0 to 10 parameters).
938 macro_rules! impl_fn_wrapper_async {
939 ($($ty:ident),*) => {
940 paste::paste! {
941 impl<F, Fut, R, $($ty,)*> ErasedFn for FnWrapperAsync<F, R, ($($ty,)*)>
942 where
943 F: Fn($($ty,)*) -> Fut + Send + Sync,
944 Fut: std::future::Future<Output = R> + Send,
945 R: IntoResult + Send + Sync,
946 $($ty: FromValue + TypedValue + Send + Sync,)*
947 {
948 fn call<'this, 'future>(
949 &'this self,
950 args: Vec<Value>
951 ) -> MaybeFuture<'future, Value, Error>
952 where 'this: 'future, Self: 'future {
953 let f = || async move {
954 // Compile-time constant: number of expected arguments
955 const EXPECTED_LEN: usize = count_args!($($ty),*);
956
957 if args.len() != EXPECTED_LEN {
958 return Err(Error::invalid_argument(
959 format!("expected {} arguments, got {}", EXPECTED_LEN, args.len())
960 ));
961 }
962
963 #[allow(unused_mut, unused_variables)]
964 let mut iter = args.iter();
965 $(
966 let [< $ty:lower >] = $ty::make_argument(
967 iter.next().expect("argument count already validated")
968 ).map_err(|e| Error::invalid_argument(format!("argument error: {}", e)))?;
969 )*
970
971 let future = (self.func)($([< $ty:lower >],)*);
972 let result = future.await;
973 result.into_result()
974 };
975 Box::pin(f()).into()
976 }
977
978 fn arguments(&self) -> Vec<ValueType> {
979 vec![$($ty::value_type()),*]
980 }
981
982 fn result(&self) -> ValueType {
983 R::value_type()
984 }
985
986 fn arguments_len(&self) -> usize {
987 count_args!($($ty),*)
988 }
989 }
990
991 // Implementation of IntoFunction for asynchronous functions
992 impl<'f, F, Fut, R, $($ty,)*> IntoFunction<'f, Async, ($($ty,)*)> for F
993 where
994 F: Fn($($ty,)*) -> Fut + Send + Sync + 'f,
995 Fut: std::future::Future<Output = R> + Send + 'f,
996 R: IntoResult + Send + Sync + 'f,
997 $($ty: FromValue + TypedValue + Send + Sync + 'f,)*
998 {
999 fn into_function(self) -> Function<'f> {
1000 Function::new(FnWrapperAsync::<F, R, ($($ty,)*)>::new(self))
1001 }
1002 }
1003
1004 // Sealed implementation for asynchronous functions
1005 impl<'f, F, Fut, R, $($ty,)*> private::Sealed<Async, ($($ty,)*)> for F
1006 where
1007 F: Fn($($ty,)*) -> Fut + Send + Sync + 'f,
1008 Fut: std::future::Future<Output = R> + Send + 'f,
1009 R: IntoResult + Send + Sync + 'f,
1010 $($ty: FromValue + TypedValue + Send + Sync + 'f,)*
1011 {}
1012 }
1013 };
1014 }
1015
1016 impl_fn_wrapper_async!();
1017 impl_fn_wrapper_async!(A1);
1018 impl_fn_wrapper_async!(A1, A2);
1019 impl_fn_wrapper_async!(A1, A2, A3);
1020 impl_fn_wrapper_async!(A1, A2, A3, A4);
1021 impl_fn_wrapper_async!(A1, A2, A3, A4, A5);
1022 impl_fn_wrapper_async!(A1, A2, A3, A4, A5, A6);
1023 impl_fn_wrapper_async!(A1, A2, A3, A4, A5, A6, A7);
1024 impl_fn_wrapper_async!(A1, A2, A3, A4, A5, A6, A7, A8);
1025 impl_fn_wrapper_async!(A1, A2, A3, A4, A5, A6, A7, A8, A9);
1026 impl_fn_wrapper_async!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
1027}
1028
1029// =============================================================================
1030// Additional implementations
1031// =============================================================================
1032
1033/// Debug implementation for type-erased functions.
1034impl std::fmt::Debug for dyn ErasedFn + '_ {
1035 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1036 f.write_str("<function>")
1037 }
1038}
1039
1040/// Private module for sealed traits to prevent external implementations.
1041mod private {
1042 #[derive(Debug)]
1043 pub enum Placeholder {}
1044
1045 pub trait Sealed<T = Placeholder, U = Placeholder> {}
1046}
1047
1048#[cfg(test)]
1049mod tests {
1050 use super::*;
1051
1052 #[test]
1053 fn test_basic_function_registration() {
1054 // Test basic function registration and metadata extraction
1055 fn add(a: i64, b: i64) -> i64 {
1056 a + b
1057 }
1058 let func = add.into_function();
1059
1060 assert_eq!(func.arguments(), vec![ValueType::Int, ValueType::Int]);
1061 assert_eq!(func.result(), ValueType::Int);
1062
1063 // Test closure registration
1064 let multiplier = 3;
1065 let multiply = move |x: i64| -> i64 { x * multiplier };
1066 let func2 = multiply.into_function();
1067
1068 assert_eq!(func2.arguments(), vec![ValueType::Int]);
1069 assert_eq!(func2.result(), ValueType::Int);
1070 }
1071
1072 #[test]
1073 fn test_reference_return_functions() {
1074 // Test functions that return borrowed data
1075 fn return_arg(a: &str) -> &str {
1076 a
1077 }
1078 let func = return_arg.into_function();
1079
1080 assert_eq!(func.arguments(), vec![ValueType::String]);
1081 assert_eq!(func.result(), ValueType::String);
1082
1083 // Test function invocation
1084 let result = func.call(vec!["hello".into()]);
1085 #[cfg(feature = "async")]
1086 let result = result.expect_result("test_reference_return_functions");
1087 assert_eq!(result.unwrap(), "hello".into());
1088 }
1089
1090 #[test]
1091 fn test_closure_with_captured_data() {
1092 // Test closures that capture environment variables
1093 let prefix = String::from("Hello, ");
1094 let with_prefix = move |name: &str| -> String { format!("{prefix}{name}") };
1095
1096 let func = with_prefix.into_function();
1097
1098 assert_eq!(func.arguments(), vec![ValueType::String]);
1099 assert_eq!(func.result(), ValueType::String);
1100
1101 // Test function invocation
1102 let result = func.call(vec!["world".into()]);
1103 #[cfg(feature = "async")]
1104 let result = result.expect_result("test_closure_with_captured_data");
1105 assert_eq!(result.unwrap(), "Hello, world".into());
1106 }
1107
1108 #[test]
1109 fn test_zero_parameter_function() {
1110 // Test functions with no parameters
1111 fn get_answer() -> i64 {
1112 42
1113 }
1114 let func = get_answer.into_function();
1115
1116 assert_eq!(func.arguments(), vec![]);
1117 assert_eq!(func.result(), ValueType::Int);
1118
1119 // Test function invocation
1120 let result = func.call(vec![]);
1121 #[cfg(feature = "async")]
1122 let result = result.expect_result("test_zero_parameter_function");
1123 assert_eq!(result.unwrap(), 42i64.into());
1124 }
1125
1126 #[test]
1127 fn test_multiple_parameter_function() {
1128 // Test functions with multiple parameters
1129 fn add_three(a: i64, b: i64, c: i64) -> i64 {
1130 a + b + c
1131 }
1132 let func = add_three.into_function();
1133
1134 assert_eq!(
1135 func.arguments(),
1136 vec![ValueType::Int, ValueType::Int, ValueType::Int]
1137 );
1138 assert_eq!(func.result(), ValueType::Int);
1139
1140 // Test function invocation
1141 let result = func.call(vec![1i64.into(), 2i64.into(), 3i64.into()]);
1142 #[cfg(feature = "async")]
1143 let result = result.expect_result("test_multiple_parameter_function");
1144 assert_eq!(result.unwrap(), 6i64.into());
1145 }
1146
1147 #[test]
1148 fn test_result_error_handling() {
1149 // Test functions that return Result for error handling
1150 fn divide(a: i64, b: i64) -> Result<i64, std::io::Error> {
1151 if b == 0 {
1152 Err(std::io::Error::new(
1153 std::io::ErrorKind::InvalidInput,
1154 "division by zero",
1155 ))
1156 } else {
1157 Ok(a / b)
1158 }
1159 }
1160
1161 let func = divide.into_function();
1162
1163 assert_eq!(func.arguments(), vec![ValueType::Int, ValueType::Int]);
1164 assert_eq!(func.result(), ValueType::Int);
1165
1166 // Test successful case
1167 let result = func.call(vec![10i64.into(), 2i64.into()]);
1168 #[cfg(feature = "async")]
1169 let result = result.expect_result("test_result_error_handling_success");
1170 assert_eq!(result.unwrap(), 5i64.into());
1171
1172 // Test error case
1173 let result = func.call(vec![10i64.into(), 0i64.into()]);
1174 #[cfg(feature = "async")]
1175 let result = result.expect_result("test_result_error_handling_error");
1176 assert!(result.is_err());
1177 }
1178}