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}