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//! # #[cfg(feature = "async")]
168//! # use cel_cxx::function::*;
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
232/// Trait for types that can be converted into function implementations.
233///
234/// This is the main entry point for function registration. Any Rust function
235/// or closure that meets the constraints can be converted into a [`Function`].
236///
237/// # Type System Integration
238///
239/// The trait uses Rust's type system to automatically:
240/// - Extract function signatures using [`FunctionDecl`]
241/// - Handle argument conversion using [`FromValue`] with GATs
242/// - Manage return type conversion using [`IntoResult`]
243/// - Support both synchronous and asynchronous functions
244///
245/// # Generic Associated Types (GATs)
246///
247/// This trait leverages GATs to handle complex lifetime relationships:
248/// - Functions returning `&str` can borrow from input parameters
249/// - Closures can capture environment variables with appropriate lifetimes
250/// - The system maintains memory safety through controlled lifetime erasure
251///
252/// # Note
253///
254/// This trait is sealed and cannot be implemented outside this crate.
255///
256/// # Type Parameters
257///
258/// - `'f`: Lifetime parameter for captured data in closures
259/// - `Fm`: Function marker (sync/async)
260/// - `Args`: Argument tuple type
261///
262/// # Examples
263///
264/// ## Simple Functions
265///
266/// ```rust
267/// # use cel_cxx::function::IntoFunction;
268/// # use std::convert::Infallible;
269/// fn add(a: i64, b: i64) -> i64 { a + b }
270/// fn divide(a: i64, b: i64) -> Result<f64, Infallible> {
271/// Ok(a as f64 / b as f64)
272/// }
273///
274/// let add_func = add.into_function();
275/// let div_func = divide.into_function();
276/// ```
277///
278/// ## Closures with Captured Variables
279///
280/// ```rust
281/// # use cel_cxx::function::IntoFunction;
282/// let factor = 2.5;
283/// let scale = move |x: f64| -> f64 { x * factor };
284/// let scale_func = scale.into_function();
285/// ```
286///
287/// ## Functions with Reference Parameters
288///
289/// ```rust
290/// # use cel_cxx::function::IntoFunction;
291/// fn process_text(text: &str, uppercase: bool) -> String {
292/// if uppercase { text.to_uppercase() } else { text.to_lowercase() }
293/// }
294/// let process_func = process_text.into_function();
295/// ```
296pub trait IntoFunction<'f, Fm: FnMarker, Args = ()>: private::Sealed<Fm, Args> {
297 /// Convert this function into a type-erased implementation.
298 ///
299 /// This method performs the conversion from a strongly-typed Rust function
300 /// to a type-erased [`Function`] that can be called from CEL expressions.
301 ///
302 /// # Returns
303 ///
304 /// A [`Function`] that encapsulates the original function with:
305 /// - Type-safe argument conversion
306 /// - Return value conversion
307 /// - Error handling
308 /// - Async support (if applicable)
309 ///
310 /// # Performance
311 ///
312 /// The conversion is zero-cost at runtime. All type checking and conversion
313 /// logic is generated at compile time.
314 fn into_function(self) -> Function<'f>;
315}
316
317/// A type-erased function implementation that can be called from CEL expressions.
318///
319/// This is the main type used to store and invoke registered functions.
320/// It provides a uniform interface for calling functions regardless of
321/// their original signature.
322///
323/// # Design
324///
325/// The `Function` struct uses dynamic dispatch through trait objects to provide
326/// a uniform interface while maintaining type safety. The original function's
327/// type information is preserved through internal trait implementations.
328///
329/// # Memory Safety
330///
331/// Despite using type erasure, the system maintains complete memory safety:
332/// - All conversions are checked at runtime
333/// - Lifetime relationships are preserved where possible
334/// - Reference parameters are handled safely through controlled lifetime management
335///
336/// # Performance
337///
338/// - Function calls involve minimal overhead (one virtual call + conversions)
339/// - Argument validation is performed once per call
340/// - Type conversions use zero-copy where possible
341///
342/// # Examples
343///
344/// ## Basic Usage
345///
346/// ```rust
347/// # use cel_cxx::function::*;
348/// fn greet(name: &str) -> String {
349/// format!("Hello, {}!", name)
350/// }
351///
352/// let func = greet.into_function();
353/// let args = vec!["World".into()];
354/// let result = func.call(args);
355/// ```
356///
357/// ## Metadata Inspection
358///
359/// ```rust
360/// # use cel_cxx::function::*;
361/// # fn greet(name: &str) -> String { format!("Hello, {}!", name) }
362/// let func = greet.into_function();
363///
364/// // Inspect function signature
365/// println!("Arguments: {:?}", func.arguments());
366/// println!("Return type: {:?}", func.result());
367/// println!("Function type: {:?}", func.function_type());
368/// ```
369#[derive(Debug, Clone)]
370pub struct Function<'f> {
371 inner: Arc<dyn ErasedFn + 'f>,
372}
373
374impl<'f> Function<'f> {
375 /// Create a new function implementation from an `ErasedFn`.
376 fn new(inner: impl ErasedFn + 'f) -> Self {
377 Self {
378 inner: Arc::new(inner),
379 }
380 }
381
382 /// Call the function with the provided arguments.
383 ///
384 /// This method invokes the function with type-safe argument conversion
385 /// and return value handling. It supports both synchronous and asynchronous
386 /// functions through the [`MaybeFuture`] return type.
387 ///
388 /// # Arguments
389 ///
390 /// * `args` - Vector of [`Value`] arguments to pass to the function
391 ///
392 /// # Returns
393 ///
394 /// Returns a [`MaybeFuture`] that represents either an immediate result or a future:
395 ///
396 /// - **Without `async` feature**: [`MaybeFuture`] is `Result<Value, Error>` - returns immediately
397 /// - **With `async` feature**: [`MaybeFuture`] can be either:
398 /// - `MaybeFuture::Result(Result<Value, Error>)` for synchronous functions
399 /// - `MaybeFuture::Future(BoxFuture<Result<Value, Error>>)` for async functions
400 ///
401 /// # Type Safety
402 ///
403 /// The method performs runtime type checking to ensure:
404 /// - Correct number of arguments is provided
405 /// - Each argument can be converted to the expected parameter type
406 /// - Return value conversion succeeds
407 ///
408 /// # Errors
409 ///
410 /// Returns an [`Error`] if:
411 /// - The number of arguments doesn't match the function signature
412 /// - Argument types cannot be converted to the expected types
413 /// - The function itself returns an error
414 /// - Return value conversion fails
415 ///
416 /// # Examples
417 ///
418 /// ## Synchronous function call
419 ///
420 /// ```rust
421 /// # use cel_cxx::function::*;
422 /// # use cel_cxx::values::Value;
423 /// fn add(a: i64, b: i64) -> i64 { a + b }
424 /// let func = add.into_function();
425 ///
426 /// let args = vec![Value::Int(10), Value::Int(20)];
427 /// let maybe_result = func.call(args);
428 ///
429 /// // In sync mode, extract the result directly
430 /// # #[cfg(not(feature = "async"))]
431 /// let result = maybe_result.unwrap();
432 ///
433 /// // In async mode, check if it's an immediate result
434 /// # #[cfg(feature = "async")]
435 /// let result = maybe_result.expect_result("shoud be result")?;
436 ///
437 /// assert_eq!(result, Value::Int(30));
438 /// # Ok::<(), cel_cxx::Error>(())
439 /// ```
440 ///
441 /// ## Async function call (when `async` feature is enabled)
442 ///
443 /// ```rust
444 /// # #[cfg(feature = "async")]
445 /// # async fn example() {
446 /// # use cel_cxx::function::*;
447 /// # use cel_cxx::values::Value;
448 /// async fn async_multiply(a: i64, b: i64) -> i64 { a * b }
449 /// let func = async_multiply.into_function();
450 ///
451 /// let args = vec![Value::Int(6), Value::Int(7)];
452 /// let maybe_result = func.call(args);
453 ///
454 /// // For async functions, extract and await the future
455 /// let result = maybe_result.unwrap_future().await.unwrap();
456 /// assert_eq!(result, Value::Int(42));
457 /// # }
458 /// ```
459 pub fn call<'this, 'future>(&'this self, args: Vec<Value>) -> MaybeFuture<'future, Value, Error>
460 where
461 'this: 'future,
462 Self: 'future,
463 {
464 self.inner.call(args)
465 }
466
467 /// Get the expected argument types for this function.
468 ///
469 /// Returns the function signature information that can be used for:
470 /// - Compile-time type checking
471 /// - Runtime argument validation
472 /// - Documentation generation
473 /// - IDE support and auto-completion
474 ///
475 /// # Returns
476 ///
477 /// A vector of [`ValueType`] representing the expected argument types
478 /// in the order they should be provided to [`call`](Self::call).
479 ///
480 /// # Examples
481 ///
482 /// ```rust
483 /// # use cel_cxx::function::*;
484 /// # use cel_cxx::types::ValueType;
485 /// fn process(name: &str, count: i64, active: bool) -> String {
486 /// format!("{}: {} ({})", name, count, active)
487 /// }
488 /// let func = process.into_function();
489 ///
490 /// let arg_types = func.arguments();
491 /// assert_eq!(arg_types, vec![
492 /// ValueType::String,
493 /// ValueType::Int,
494 /// ValueType::Bool
495 /// ]);
496 /// ```
497 pub fn arguments(&self) -> Vec<ValueType> {
498 self.inner.arguments()
499 }
500
501 /// Get the return type of this function.
502 ///
503 /// Returns type information that can be used for:
504 /// - Compile-time type checking of expressions
505 /// - Runtime result validation
506 /// - Type inference in complex expressions
507 ///
508 /// # Returns
509 ///
510 /// The [`ValueType`] that this function returns when called successfully.
511 /// For functions returning `Result<T, E>`, this returns the success type `T`.
512 ///
513 /// # Examples
514 ///
515 /// ```rust
516 /// # use cel_cxx::function::*;
517 /// # use cel_cxx::types::ValueType;
518 /// fn calculate(x: f64, y: f64) -> f64 { x * y + 1.0 }
519 /// let func = calculate.into_function();
520 ///
521 /// assert_eq!(func.result(), ValueType::Double);
522 /// ```
523 ///
524 /// ```rust
525 /// # use cel_cxx::function::*;
526 /// # use cel_cxx::types::ValueType;
527 /// # use std::convert::Infallible;
528 /// fn get_message() -> Result<String, Infallible> {
529 /// Ok("Hello".to_string())
530 /// }
531 /// let func = get_message.into_function();
532 ///
533 /// // Returns the success type, not Result<String, Infallible>
534 /// assert_eq!(func.result(), ValueType::String);
535 /// ```
536 pub fn result(&self) -> ValueType {
537 self.inner.result()
538 }
539
540 /// Get complete function type information.
541 ///
542 /// Returns a [`FunctionType`] that combines argument and return type information.
543 /// This is useful for:
544 /// - Function signature matching
545 /// - Overload resolution
546 /// - Type checking in complex expressions
547 ///
548 /// # Returns
549 ///
550 /// A [`FunctionType`] containing complete function signature information.
551 ///
552 /// # Examples
553 ///
554 /// ```rust
555 /// # use cel_cxx::function::*;
556 /// # use cel_cxx::types::{ValueType, FunctionType};
557 /// fn multiply(a: i64, b: i64) -> i64 { a * b }
558 /// let func = multiply.into_function();
559 ///
560 /// let func_type = func.function_type();
561 /// assert_eq!(func_type.arguments(), &[ValueType::Int, ValueType::Int]);
562 /// assert_eq!(func_type.result(), &ValueType::Int);
563 /// ```
564 pub fn function_type(&self) -> FunctionType {
565 FunctionType::new(self.result(), self.arguments())
566 }
567
568 /// Get the number of arguments this function expects.
569 ///
570 /// This is a convenience method equivalent to `self.arguments().len()`.
571 /// Useful for quick arity checking without allocating the full argument
572 /// type vector.
573 ///
574 /// # Returns
575 ///
576 /// The number of parameters this function expects.
577 ///
578 /// # Examples
579 ///
580 /// ```rust
581 /// # use cel_cxx::function::*;
582 /// fn no_args() -> i64 { 42 }
583 /// fn one_arg(x: i64) -> i64 { x }
584 /// fn three_args(a: i64, b: i64, c: i64) -> i64 { a + b + c }
585 ///
586 /// assert_eq!(no_args.into_function().arguments_len(), 0);
587 /// assert_eq!(one_arg.into_function().arguments_len(), 1);
588 /// assert_eq!(three_args.into_function().arguments_len(), 3);
589 /// ```
590 pub fn arguments_len(&self) -> usize {
591 self.inner.arguments_len()
592 }
593}
594
595// =============================================================================
596// Implementation details
597// =============================================================================
598
599/// Internal trait for type-erased function implementations.
600///
601/// This trait provides a uniform interface for calling functions regardless
602/// of their original signature. It is not exposed publicly as users should
603/// interact with [`Function`] instead.
604trait ErasedFn: Send + Sync {
605 /// Call the function with the provided arguments.
606 fn call<'this, 'future>(&'this self, args: Vec<Value>) -> MaybeFuture<'future, Value, Error>
607 where
608 'this: 'future,
609 Self: 'future;
610
611 /// Get the expected argument types.
612 fn arguments(&self) -> Vec<ValueType>;
613
614 /// Get the return type.
615 fn result(&self) -> ValueType;
616
617 /// Get the number of expected arguments.
618 fn arguments_len(&self) -> usize;
619}
620
621macro_rules! impl_arguments {
622 ($(
623 $($ty:ident),+
624 )?) => {
625 impl<$($($ty: FromValue + TypedValue),+)?> Arguments for ($($($ty,)+)?) {}
626 impl<$($($ty: FromValue + TypedValue),+)?> private::Sealed for ($($($ty,)+)?) {}
627 }
628}
629
630impl_arguments!();
631impl_arguments!(A1);
632impl_arguments!(A1, A2);
633impl_arguments!(A1, A2, A3);
634impl_arguments!(A1, A2, A3, A4);
635impl_arguments!(A1, A2, A3, A4, A5);
636impl_arguments!(A1, A2, A3, A4, A5, A6);
637impl_arguments!(A1, A2, A3, A4, A5, A6, A7);
638impl_arguments!(A1, A2, A3, A4, A5, A6, A7, A8);
639impl_arguments!(A1, A2, A3, A4, A5, A6, A7, A8, A9);
640impl_arguments!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
641
642/// Internal trait for safely converting `FromValue::Output` to function parameter types.
643///
644/// This trait contains unsafe code for lifetime erasure and should only be used
645/// within the controlled context of function dispatch. It is not exposed publicly
646/// to ensure memory safety.
647trait Argument: FromValue + TypedValue {
648 /// Convert a CEL value to the function parameter type.
649 ///
650 /// This method safely converts a [`Value`] reference to the target type
651 /// by first using [`FromValue::from_value`] and then performing controlled
652 /// lifetime erasure via [`Self::from_output`].
653 fn make_argument(value: &Value) -> Result<Self, FromValueError> {
654 let output = <Self as FromValue>::from_value(value)?;
655 Ok(unsafe { Self::from_output(output) })
656 }
657
658 /// Convert `FromValue::Output<'a>` to `Self` by erasing lifetime information.
659 ///
660 /// # Safety
661 ///
662 /// This method performs an unsafe lifetime erasure operation that is only safe
663 /// under specific controlled conditions:
664 ///
665 /// 1. **Memory Layout Guarantee**: The method assumes that `Self` and
666 /// `Self::Output<'a>` have identical memory layouts. This is verified by
667 /// a debug assertion checking `size_of` equality.
668 ///
669 /// 2. **Lifetime Erasure Safety**: The lifetime parameter 'a is erased through
670 /// unsafe pointer casting. This is safe because:
671 /// - The input `output` is consumed (moved) into this function
672 /// - The returned `Self` will be immediately consumed by the function call
673 /// - No references escape the function call scope
674 ///
675 /// 3. **Controlled Usage Context**: This method is only called within the
676 /// function dispatch mechanism where:
677 /// - The source `&[Value]` array remains valid for the entire function call
678 /// - The converted arguments are immediately passed to the target function
679 /// - The function result is immediately converted via `IntoResult`
680 ///
681 /// 4. **Type System Cooperation**: For reference types like `&str`:
682 /// - `Self::Output<'a>` is `&'a str` (borrowed from Value)
683 /// - `Self` is `&str` (with erased lifetime)
684 /// - The underlying string data in Value remains valid throughout the call
685 ///
686 /// The safety of this operation relies on the fact that the lifetime erasure
687 /// is temporary and scoped - the converted values never outlive the original
688 /// Value array that owns the underlying data.
689 ///
690 /// # Implementation Details
691 ///
692 /// The conversion process:
693 /// 1. Cast the reference to `output` as a pointer to `Self`
694 /// 2. Forget the original `output` to prevent double-drop
695 /// 3. Read the value from the pointer, effectively transferring ownership
696 ///
697 /// This is essentially a controlled `transmute` operation that preserves
698 /// the bit representation while changing the type signature.
699 unsafe fn from_output<'a>(output: <Self as FromValue>::Output<'a>) -> Self {
700 debug_assert!(
701 std::mem::size_of::<<Self as FromValue>::Output<'a>>() == std::mem::size_of::<Self>()
702 );
703
704 let ptr: *const Self = (&output as *const <Self as FromValue>::Output<'a>).cast();
705 std::mem::forget(output);
706 std::ptr::read(ptr)
707 }
708}
709
710// Blanket implementation for all types that implement FromValue and TypedValue
711impl<T: FromValue + TypedValue> Argument for T {}
712
713/// Internal wrapper for synchronous functions that implements [`ErasedFn`].
714///
715/// This struct wraps a function along with phantom data for its signature,
716/// allowing type-erased storage and invocation.
717struct FnWrapper<F, R, Args> {
718 func: F,
719 _phantom: std::marker::PhantomData<(R, Args)>,
720}
721
722impl<F, R, Args> FnWrapper<F, R, Args> {
723 /// Create a new function wrapper.
724 fn new(func: F) -> Self {
725 Self {
726 func,
727 _phantom: std::marker::PhantomData,
728 }
729 }
730}
731
732// =============================================================================
733// Helper macros and implementations
734// =============================================================================
735
736/// Compile-time macro to count the number of function arguments.
737macro_rules! count_args {
738 () => { 0 };
739 ($head:ident $(, $tail:ident)*) => { 1 + count_args!($($tail),*) };
740}
741use count_args;
742
743/// Macro to generate [`ErasedFn`] implementations for synchronous functions
744/// with different arities (0 to 10 parameters).
745macro_rules! impl_fn_wrapper {
746 ($($ty:ident),*) => {
747 paste::paste! {
748 impl<F, R, $($ty,)*> ErasedFn for FnWrapper<F, R, ($($ty,)*)>
749 where
750 F: Fn($($ty,)*) -> R + Send + Sync,
751 R: IntoResult + Send + Sync,
752 $($ty: FromValue + TypedValue + Send + Sync,)*
753 {
754 fn call<'this, 'future>(
755 &'this self,
756 args: Vec<Value>
757 ) -> MaybeFuture<'future, Value, Error>
758 where 'this: 'future, Self: 'future {
759 let f = || {
760 // Compile-time constant: number of expected arguments
761 const EXPECTED_LEN: usize = count_args!($($ty),*);
762
763 if args.len() != EXPECTED_LEN {
764 return Err(Error::invalid_argument(
765 format!("expected {} arguments, got {}", EXPECTED_LEN, args.len())
766 ));
767 }
768
769 #[allow(unused_mut, unused_variables)]
770 let mut iter = args.iter();
771 $(
772 let [< $ty:lower >] = $ty::make_argument(
773 iter.next().expect("argument count already validated")
774 ).map_err(|e| Error::invalid_argument(format!("argument error: {}", e)))?;
775 )*
776
777 let result = (self.func)($([< $ty:lower >],)*);
778 result.into_result()
779 };
780 f().into()
781 }
782
783 fn arguments(&self) -> Vec<ValueType> {
784 vec![$($ty::value_type()),*]
785 }
786
787 fn result(&self) -> ValueType {
788 R::value_type()
789 }
790
791 fn arguments_len(&self) -> usize {
792 count_args!($($ty),*)
793 }
794 }
795
796 // Implementation of IntoFunction for synchronous functions
797 impl<'f, F, R, $($ty,)*> IntoFunction<'f, (), ($($ty,)*)> for F
798 where
799 F: Fn($($ty,)*) -> R + Send + Sync + 'f,
800 R: IntoResult + Send + Sync + 'f,
801 ($($ty,)*): Arguments,
802 $($ty: FromValue + TypedValue + Send + Sync + 'f,)*
803 {
804 fn into_function(self) -> Function<'f> {
805 Function::new(FnWrapper::<F, R, ($($ty,)*)>::new(self))
806 }
807 }
808
809 // Sealed implementation for synchronous functions
810 impl<'f, F, R, $($ty,)*> private::Sealed<(), ($($ty,)*)> for F
811 where
812 F: Fn($($ty,)*) -> R + Send + Sync + 'f,
813 R: IntoResult + Send + Sync + 'f,
814 ($($ty,)*): Arguments,
815 $($ty: FromValue + TypedValue + Send + Sync + 'f,)*
816 {}
817 }
818 };
819}
820
821// Generate implementations for functions with 0-10 parameters
822impl_fn_wrapper!();
823impl_fn_wrapper!(A1);
824impl_fn_wrapper!(A1, A2);
825impl_fn_wrapper!(A1, A2, A3);
826impl_fn_wrapper!(A1, A2, A3, A4);
827impl_fn_wrapper!(A1, A2, A3, A4, A5);
828impl_fn_wrapper!(A1, A2, A3, A4, A5, A6);
829impl_fn_wrapper!(A1, A2, A3, A4, A5, A6, A7);
830impl_fn_wrapper!(A1, A2, A3, A4, A5, A6, A7, A8);
831impl_fn_wrapper!(A1, A2, A3, A4, A5, A6, A7, A8, A9);
832impl_fn_wrapper!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
833
834// =============================================================================
835// Async function support (optional feature)
836// =============================================================================
837
838/// Internal wrapper for asynchronous functions that implements [`ErasedFn`].
839///
840/// This struct is similar to [`FnWrapper`] but designed for async functions
841/// that return futures. It's only available when the `async` feature is enabled.
842#[cfg(feature = "async")]
843#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
844struct FnWrapperAsync<F, R, Args> {
845 func: F,
846 _phantom: std::marker::PhantomData<(R, Args)>,
847}
848
849#[cfg(feature = "async")]
850#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
851impl<F, R, Args> FnWrapperAsync<F, R, Args> {
852 /// Create a new async function wrapper.
853 fn new(func: F) -> Self {
854 Self {
855 func,
856 _phantom: std::marker::PhantomData,
857 }
858 }
859}
860
861#[cfg(feature = "async")]
862#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
863mod async_impls {
864 use super::*;
865
866 /// Macro to generate [`ErasedFn`] implementations for asynchronous functions
867 /// with different arities (0 to 10 parameters).
868 macro_rules! impl_fn_wrapper_async {
869 ($($ty:ident),*) => {
870 paste::paste! {
871 impl<F, Fut, R, $($ty,)*> ErasedFn for FnWrapperAsync<F, R, ($($ty,)*)>
872 where
873 F: Fn($($ty,)*) -> Fut + Send + Sync,
874 Fut: std::future::Future<Output = R> + Send,
875 R: IntoResult + Send + Sync,
876 $($ty: FromValue + TypedValue + Send + Sync,)*
877 {
878 fn call<'this, 'future>(
879 &'this self,
880 args: Vec<Value>
881 ) -> MaybeFuture<'future, Value, Error>
882 where 'this: 'future, Self: 'future {
883 let f = || async move {
884 // Compile-time constant: number of expected arguments
885 const EXPECTED_LEN: usize = count_args!($($ty),*);
886
887 if args.len() != EXPECTED_LEN {
888 return Err(Error::invalid_argument(
889 format!("expected {} arguments, got {}", EXPECTED_LEN, args.len())
890 ));
891 }
892
893 #[allow(unused_mut, unused_variables)]
894 let mut iter = args.iter();
895 $(
896 let [< $ty:lower >] = $ty::make_argument(
897 iter.next().expect("argument count already validated")
898 ).map_err(|e| Error::invalid_argument(format!("argument error: {}", e)))?;
899 )*
900
901 let future = (self.func)($([< $ty:lower >],)*);
902 let result = future.await;
903 result.into_result()
904 };
905 Box::pin(f()).into()
906 }
907
908 fn arguments(&self) -> Vec<ValueType> {
909 vec![$($ty::value_type()),*]
910 }
911
912 fn result(&self) -> ValueType {
913 R::value_type()
914 }
915
916 fn arguments_len(&self) -> usize {
917 count_args!($($ty),*)
918 }
919 }
920
921 // Implementation of IntoFunction for asynchronous functions
922 impl<'f, F, Fut, R, $($ty,)*> IntoFunction<'f, Async, ($($ty,)*)> for F
923 where
924 F: Fn($($ty,)*) -> Fut + Send + Sync + 'f,
925 Fut: std::future::Future<Output = R> + Send + 'f,
926 R: IntoResult + Send + Sync + 'f,
927 $($ty: FromValue + TypedValue + Send + Sync + 'f,)*
928 {
929 fn into_function(self) -> Function<'f> {
930 Function::new(FnWrapperAsync::<F, R, ($($ty,)*)>::new(self))
931 }
932 }
933
934 // Sealed implementation for asynchronous functions
935 impl<'f, F, Fut, R, $($ty,)*> private::Sealed<Async, ($($ty,)*)> for F
936 where
937 F: Fn($($ty,)*) -> Fut + Send + Sync + 'f,
938 Fut: std::future::Future<Output = R> + Send + 'f,
939 R: IntoResult + Send + Sync + 'f,
940 $($ty: FromValue + TypedValue + Send + Sync + 'f,)*
941 {}
942 }
943 };
944 }
945
946 impl_fn_wrapper_async!();
947 impl_fn_wrapper_async!(A1);
948 impl_fn_wrapper_async!(A1, A2);
949 impl_fn_wrapper_async!(A1, A2, A3);
950 impl_fn_wrapper_async!(A1, A2, A3, A4);
951 impl_fn_wrapper_async!(A1, A2, A3, A4, A5);
952 impl_fn_wrapper_async!(A1, A2, A3, A4, A5, A6);
953 impl_fn_wrapper_async!(A1, A2, A3, A4, A5, A6, A7);
954 impl_fn_wrapper_async!(A1, A2, A3, A4, A5, A6, A7, A8);
955 impl_fn_wrapper_async!(A1, A2, A3, A4, A5, A6, A7, A8, A9);
956 impl_fn_wrapper_async!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
957}
958
959// =============================================================================
960// Additional implementations
961// =============================================================================
962
963/// Debug implementation for type-erased functions.
964impl std::fmt::Debug for dyn ErasedFn + '_ {
965 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
966 f.write_str("<function>")
967 }
968}
969
970/// Private module for sealed traits to prevent external implementations.
971mod private {
972 #[derive(Debug)]
973 pub enum Placeholder {}
974
975 pub trait Sealed<T = Placeholder, U = Placeholder> {}
976}
977
978#[cfg(test)]
979mod tests {
980 use super::*;
981
982 #[test]
983 fn test_basic_function_registration() {
984 // Test basic function registration and metadata extraction
985 fn add(a: i64, b: i64) -> i64 {
986 a + b
987 }
988 let func = add.into_function();
989
990 assert_eq!(func.arguments(), vec![ValueType::Int, ValueType::Int]);
991 assert_eq!(func.result(), ValueType::Int);
992
993 // Test closure registration
994 let multiplier = 3;
995 let multiply = move |x: i64| -> i64 { x * multiplier };
996 let func2 = multiply.into_function();
997
998 assert_eq!(func2.arguments(), vec![ValueType::Int]);
999 assert_eq!(func2.result(), ValueType::Int);
1000 }
1001
1002 #[test]
1003 fn test_reference_return_functions() {
1004 // Test functions that return borrowed data
1005 fn return_arg(a: &str) -> &str {
1006 a
1007 }
1008 let func = return_arg.into_function();
1009
1010 assert_eq!(func.arguments(), vec![ValueType::String]);
1011 assert_eq!(func.result(), ValueType::String);
1012
1013 // Test function invocation
1014 let result = func.call(vec!["hello".into()]);
1015 let result = result.expect_result("test_reference_return_functions");
1016 assert_eq!(result.unwrap(), "hello".into());
1017 }
1018
1019 #[test]
1020 fn test_closure_with_captured_data() {
1021 // Test closures that capture environment variables
1022 let prefix = String::from("Hello, ");
1023 let with_prefix = move |name: &str| -> String { format!("{}{}", prefix, name) };
1024
1025 let func = with_prefix.into_function();
1026
1027 assert_eq!(func.arguments(), vec![ValueType::String]);
1028 assert_eq!(func.result(), ValueType::String);
1029
1030 // Test function invocation
1031 let result = func.call(vec!["world".into()]);
1032 let result = result.expect_result("test_closure_with_captured_data");
1033 assert_eq!(result.unwrap(), "Hello, world".into());
1034 }
1035
1036 #[test]
1037 fn test_zero_parameter_function() {
1038 // Test functions with no parameters
1039 fn get_answer() -> i64 {
1040 42
1041 }
1042 let func = get_answer.into_function();
1043
1044 assert_eq!(func.arguments(), vec![]);
1045 assert_eq!(func.result(), ValueType::Int);
1046
1047 // Test function invocation
1048 let result = func.call(vec![]);
1049 let result = result.expect_result("test_zero_parameter_function");
1050 assert_eq!(result.unwrap(), 42i64.into());
1051 }
1052
1053 #[test]
1054 fn test_multiple_parameter_function() {
1055 // Test functions with multiple parameters
1056 fn add_three(a: i64, b: i64, c: i64) -> i64 {
1057 a + b + c
1058 }
1059 let func = add_three.into_function();
1060
1061 assert_eq!(
1062 func.arguments(),
1063 vec![ValueType::Int, ValueType::Int, ValueType::Int]
1064 );
1065 assert_eq!(func.result(), ValueType::Int);
1066
1067 // Test function invocation
1068 let result = func.call(vec![1i64.into(), 2i64.into(), 3i64.into()]);
1069 let result = result.expect_result("test_multiple_parameter_function");
1070 assert_eq!(result.unwrap(), 6i64.into());
1071 }
1072
1073 #[test]
1074 fn test_result_error_handling() {
1075 // Test functions that return Result for error handling
1076 fn divide(a: i64, b: i64) -> Result<i64, std::io::Error> {
1077 if b == 0 {
1078 Err(std::io::Error::new(
1079 std::io::ErrorKind::InvalidInput,
1080 "division by zero",
1081 ))
1082 } else {
1083 Ok(a / b)
1084 }
1085 }
1086
1087 let func = divide.into_function();
1088
1089 assert_eq!(func.arguments(), vec![ValueType::Int, ValueType::Int]);
1090 assert_eq!(func.result(), ValueType::Int);
1091
1092 // Test successful case
1093 let result = func.call(vec![10i64.into(), 2i64.into()]);
1094 let result = result.expect_result("test_result_error_handling_success");
1095 assert_eq!(result.unwrap(), 5i64.into());
1096
1097 // Test error case
1098 let result = func.call(vec![10i64.into(), 0i64.into()]);
1099 let result = result.expect_result("test_result_error_handling_error");
1100 assert!(result.is_err());
1101 }
1102}