cel_cxx/function/
decl.rs

1//! Function declaration trait for CEL expression evaluation.
2//!
3//! This module provides the [`FunctionDecl`] trait for extracting compile-time type information
4//! from function signatures. The trait is used for function registration and type checking
5//! in CEL environments.
6//!
7//! # Features
8//!
9//! - **Compile-time type extraction**: Extract argument and return types from function signatures
10//! - **Sealed trait**: Cannot be implemented outside this crate for type safety
11//! - **Zero-annotation support**: Works with standard Rust function types without annotations
12//! - **Generic function support**: Supports functions with 0 to 10 parameters
13//! - **Type safety**: Ensures only valid CEL-compatible function types can be declared
14//!
15//! # Examples
16//!
17//! ## Basic function declaration
18//!
19//! ```rust
20//! use cel_cxx::function::FunctionDecl;
21//! use cel_cxx::types::ValueType;
22//!
23//! // Extract type information from function signatures
24//! type AddFn = fn(i64, i64) -> i64;
25//! let arg_types = AddFn::arguments();
26//! let return_type = AddFn::result();
27//!
28//! assert_eq!(arg_types, vec![ValueType::Int, ValueType::Int]);
29//! assert_eq!(return_type, ValueType::Int);
30//! ```
31//!
32//! ## Complex function types
33//!
34//! ```rust
35//! # use cel_cxx::function::FunctionDecl;
36//! # use cel_cxx::types::ValueType;
37//! // String processing function
38//! type FormatFn = fn(String, i64) -> String;
39//! let arg_types = FormatFn::arguments();
40//! let return_type = FormatFn::result();
41//!
42//! assert_eq!(arg_types, vec![ValueType::String, ValueType::Int]);
43//! assert_eq!(return_type, ValueType::String);
44//! ```
45//!
46//! ## Zero-parameter functions
47//!
48//! ```rust
49//! # use cel_cxx::function::FunctionDecl;
50//! # use cel_cxx::types::ValueType;
51//! // Constant function
52//! type PiFn = fn() -> f64;
53//! let arg_types = PiFn::arguments();
54//! let return_type = PiFn::result();
55//!
56//! assert_eq!(arg_types, vec![]);
57//! assert_eq!(return_type, ValueType::Double);
58//! ```
59
60use super::count_args;
61use crate::types::*;
62use crate::values::*;
63
64// =============================================================================
65// Public API
66// =============================================================================
67
68/// Trait for extracting compile-time type information from function signatures.
69///
70/// This trait provides static methods to extract argument and return type information
71/// from function pointer types. It is used purely for type declarations and does not
72/// require the ability to instantiate values, only to determine their types.
73///
74/// # Note
75///
76/// This trait is sealed and cannot be implemented outside this crate. It is
77/// automatically implemented for function pointer types with compatible signatures.
78///
79/// # Automatically Implemented For
80///
81/// The trait is implemented for function pointer types:
82/// - `fn() -> R`
83/// - `fn(A1) -> R`
84/// - `fn(A1, A2) -> R`
85/// - `fn(A1, A2, A3) -> R`
86/// - ... (up to 10 arguments)
87///
88/// Where:
89/// - `R: TypedValue` (return type must have a known CEL type)
90/// - `A1, A2, ...: TypedValue` (argument types must have known CEL types)
91///
92/// # Examples
93///
94/// ```rust
95/// # use cel_cxx::function::FunctionDecl;
96/// # use cel_cxx::types::ValueType;
97/// // Simple arithmetic function
98/// type MathFn = fn(i64, i64) -> i64;
99/// assert_eq!(MathFn::arguments(), vec![ValueType::Int, ValueType::Int]);
100/// assert_eq!(MathFn::result(), ValueType::Int);
101///
102/// // String manipulation function
103/// type StringFn = fn(String, i64) -> String;
104/// assert_eq!(StringFn::arguments(), vec![ValueType::String, ValueType::Int]);
105/// assert_eq!(StringFn::result(), ValueType::String);
106/// ```
107pub trait FunctionDecl: private::Sealed {
108    /// The number of arguments that this function signature accepts.
109    ///
110    /// This constant provides compile-time access to the arity (number of parameters)
111    /// of the function signature. It is automatically computed by the implementation
112    /// and matches the length of the vector returned by [`arguments()`](Self::arguments).
113    ///
114    /// # Examples
115    ///
116    /// ```rust
117    /// # use cel_cxx::function::FunctionDecl;
118    /// type NoArgsFn = fn() -> i64;
119    /// type TwoArgsFn = fn(i64, String) -> bool;
120    /// type ThreeArgsFn = fn(i64, String, bool) -> f64;
121    ///
122    /// assert_eq!(NoArgsFn::ARGUMENTS_LEN, 0);
123    /// assert_eq!(TwoArgsFn::ARGUMENTS_LEN, 2);
124    /// assert_eq!(ThreeArgsFn::ARGUMENTS_LEN, 3);
125    /// ```
126    const ARGUMENTS_LEN: usize;
127
128    /// Get the argument types of the function.
129    ///
130    /// Returns a vector of [`ValueType`] representing the expected argument types
131    /// in the order they should be provided to the function.
132    ///
133    /// # Returns
134    ///
135    /// A vector of [`ValueType`] values representing each parameter type.
136    fn arguments() -> Vec<ValueType>;
137
138    /// Get the return type of the function.
139    ///
140    /// Returns the [`ValueType`] that this function signature returns.
141    ///
142    /// # Returns
143    ///
144    /// The [`ValueType`] representing the function's return type.
145    fn result() -> ValueType;
146
147    /// Get the function type of the function.
148    ///
149    /// Returns the [`FunctionType`] that this function signature represents.
150    ///
151    /// # Returns
152    ///
153    /// The [`FunctionType`] is a tuple of the return type and the argument types.
154    fn function_type() -> FunctionType {
155        FunctionType::new(Self::result(), Self::arguments())
156    }
157
158    /// Get the number of arguments of the function.
159    ///
160    /// Returns the number of arguments that the function takes.
161    ///
162    /// # Returns
163    ///
164    /// The number of arguments that the function takes.
165    fn arguments_len() -> usize {
166        Self::ARGUMENTS_LEN
167    }
168}
169
170// =============================================================================
171// Implementation details
172// =============================================================================
173
174/// Macro to generate [`FunctionDecl`] implementations for function pointer types
175/// with different arities (0 to 10 parameters).
176macro_rules! impl_function_decl {
177    ($($ty:ident),*) => {
178        impl<R, $($ty,)*> FunctionDecl for fn($($ty,)*) -> R
179        where
180            R: IntoResult,
181            $($ty: TypedValue,)*
182        {
183            fn arguments() -> Vec<ValueType> {
184                vec![$($ty::value_type()),*]
185            }
186
187            fn result() -> ValueType {
188                R::value_type()
189            }
190
191            const ARGUMENTS_LEN: usize = count_args!($($ty),*);
192        }
193
194        // Sealed implementation for function pointer types
195        impl<R, $($ty,)*> private::Sealed for fn($($ty,)*) -> R
196        where
197            R: IntoResult,
198            $($ty: TypedValue,)*
199        {}
200    };
201}
202
203// Generate implementations for functions with 0-10 parameters
204impl_function_decl!();
205impl_function_decl!(A1);
206impl_function_decl!(A1, A2);
207impl_function_decl!(A1, A2, A3);
208impl_function_decl!(A1, A2, A3, A4);
209impl_function_decl!(A1, A2, A3, A4, A5);
210impl_function_decl!(A1, A2, A3, A4, A5, A6);
211impl_function_decl!(A1, A2, A3, A4, A5, A6, A7);
212impl_function_decl!(A1, A2, A3, A4, A5, A6, A7, A8);
213impl_function_decl!(A1, A2, A3, A4, A5, A6, A7, A8, A9);
214impl_function_decl!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
215
216// =============================================================================
217// Private module for sealed traits
218// =============================================================================
219
220/// Private module for sealed traits to prevent external implementations.
221mod private {
222    /// Sealed trait to prevent external implementations of [`FunctionDecl`].
223    pub trait Sealed {}
224}
225
226#[cfg(test)]
227mod tests {
228    use super::*;
229
230    #[test]
231    fn test_zero_parameter_function() {
232        // Test function with no parameters
233        type ConstantFn = fn() -> i64;
234
235        assert_eq!(ConstantFn::arguments(), vec![]);
236        assert_eq!(ConstantFn::result(), ValueType::Int);
237    }
238
239    #[test]
240    fn test_single_parameter_function() {
241        // Test function with one parameter
242        type SquareFn = fn(i64) -> i64;
243
244        assert_eq!(SquareFn::arguments(), vec![ValueType::Int]);
245        assert_eq!(SquareFn::result(), ValueType::Int);
246    }
247
248    #[test]
249    fn test_multiple_parameter_function() {
250        // Test function with multiple parameters
251        type AddFn = fn(i64, i64, i64) -> i64;
252
253        assert_eq!(
254            AddFn::arguments(),
255            vec![ValueType::Int, ValueType::Int, ValueType::Int]
256        );
257        assert_eq!(AddFn::result(), ValueType::Int);
258    }
259
260    #[test]
261    fn test_mixed_type_function() {
262        // Test function with mixed argument types
263        type FormatFn = fn(String, i64, bool) -> String;
264
265        assert_eq!(
266            FormatFn::arguments(),
267            vec![ValueType::String, ValueType::Int, ValueType::Bool]
268        );
269        assert_eq!(FormatFn::result(), ValueType::String);
270    }
271
272    #[test]
273    fn test_string_function() {
274        // Test function with string types
275        type ConcatFn = fn(String, String) -> String;
276
277        assert_eq!(
278            ConcatFn::arguments(),
279            vec![ValueType::String, ValueType::String]
280        );
281        assert_eq!(ConcatFn::result(), ValueType::String);
282    }
283
284    #[test]
285    fn test_floating_point_function() {
286        // Test function with floating point types
287        type MathFn = fn(f64, f64) -> f64;
288
289        assert_eq!(
290            MathFn::arguments(),
291            vec![ValueType::Double, ValueType::Double]
292        );
293        assert_eq!(MathFn::result(), ValueType::Double);
294    }
295
296    #[test]
297    fn test_boolean_function() {
298        // Test function with boolean types
299        type LogicFn = fn(bool, bool) -> bool;
300
301        assert_eq!(LogicFn::arguments(), vec![ValueType::Bool, ValueType::Bool]);
302        assert_eq!(LogicFn::result(), ValueType::Bool);
303    }
304
305    #[test]
306    fn test_maximum_parameters() {
307        // Test function with maximum supported parameters (10)
308        type MaxParamFn = fn(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64) -> i64;
309
310        let expected_args = vec![ValueType::Int; 10];
311        assert_eq!(MaxParamFn::arguments(), expected_args);
312        assert_eq!(MaxParamFn::result(), ValueType::Int);
313    }
314}