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/// Marker trait for function declarations with at least one parameter.
171///
172/// This trait extends [`FunctionDecl`] to identify function signatures that have
173/// at least one argument. It is used to restrict member function declarations
174/// to ensure that member functions always have a receiver object as their first
175/// parameter.
176///
177/// # Purpose
178///
179/// Member functions in CEL must have at least one argument (the receiver object).
180/// This trait provides compile-time type checking to enforce this constraint
181/// when declaring member functions through [`FunctionRegistry::declare_member`]
182/// or [`EnvBuilder::declare_member_function`].
183///
184/// # Implementation Details
185///
186/// This trait is automatically implemented for all non-empty function signatures
187/// (1 to 10 parameters) through the [`impl_function_decl!`] macro. The zero-parameter
188/// function type `fn() -> R` implements [`FunctionDecl`] but does not implement
189/// `FunctionDeclWithNonEmptyArguments`, which allows the type system to distinguish between
190/// zero-argument and non-zero-argument function declarations.
191///
192/// # Usage in Member Function Declarations
193///
194/// When declaring a member function, the type system requires:
195/// ```rust,ignore
196/// D: FunctionDecl + FunctionDeclWithNonEmptyArguments
197/// ```
198///
199/// This constraint ensures that:
200/// - Member function declarations cannot have zero arguments
201/// - The first argument of a member function represents the receiver object
202/// - Type safety is enforced at compile time
203///
204/// # Examples
205///
206/// Valid member function declaration signatures (implement `FunctionDeclWithNonEmptyArguments`):
207/// - `fn(String) -> i64` - one argument
208/// - `fn(String, i64) -> bool` - two arguments
209/// - `fn(Vec<i64>, bool) -> String` - two arguments
210///
211/// Invalid member function declaration signature (does not implement `FunctionDeclWithNonEmptyArguments`):
212/// - `fn() -> i64` - zero arguments (cannot be used for member function declarations)
213///
214/// # Note
215///
216/// This trait is sealed and cannot be implemented outside this crate.
217/// It is automatically implemented for function pointer types with 1 to 10 parameters.
218pub trait FunctionDeclWithNonEmptyArguments: FunctionDecl + private::Sealed {}
219
220// =============================================================================
221// Implementation details
222// =============================================================================
223
224/// Macro to generate [`FunctionDecl`] implementations for function pointer types
225/// with different arities (0 to 10 parameters).
226macro_rules! impl_function_decl {
227    () => {
228        impl<R> FunctionDecl for fn() -> R
229        where
230            R: IntoResult,
231        {
232            fn arguments() -> Vec<ValueType> {
233                vec![]
234            }
235
236            fn result() -> ValueType {
237                R::value_type()
238            }
239
240            const ARGUMENTS_LEN: usize = 0;
241        }
242
243        // Sealed implementation for zero-parameter function pointer types
244        impl<R> private::Sealed for fn() -> R
245        where
246            R: IntoResult,
247        {}
248    };
249    (
250        $($ty:ident),+
251    ) => {
252        impl<R, $($ty,)*> FunctionDecl for fn($($ty,)*) -> R
253        where
254            R: IntoResult,
255            $($ty: TypedValue,)*
256        {
257            fn arguments() -> Vec<ValueType> {
258                vec![$($ty::value_type()),*]
259            }
260
261            fn result() -> ValueType {
262                R::value_type()
263            }
264
265            const ARGUMENTS_LEN: usize = count_args!($($ty),*);
266        }
267
268        impl<R, $($ty,)*> FunctionDeclWithNonEmptyArguments for fn($($ty,)*) -> R
269        where
270            R: IntoResult,
271            $($ty: TypedValue,)*
272        {}
273
274        // Sealed implementation for non-empty function pointer types
275        impl<R, $($ty,)*> private::Sealed for fn($($ty,)*) -> R
276        where
277            R: IntoResult,
278            $($ty: TypedValue,)*
279        {}
280    };
281}
282
283// Generate implementations for functions with 0-10 parameters
284impl_function_decl!();
285impl_function_decl!(A1);
286impl_function_decl!(A1, A2);
287impl_function_decl!(A1, A2, A3);
288impl_function_decl!(A1, A2, A3, A4);
289impl_function_decl!(A1, A2, A3, A4, A5);
290impl_function_decl!(A1, A2, A3, A4, A5, A6);
291impl_function_decl!(A1, A2, A3, A4, A5, A6, A7);
292impl_function_decl!(A1, A2, A3, A4, A5, A6, A7, A8);
293impl_function_decl!(A1, A2, A3, A4, A5, A6, A7, A8, A9);
294impl_function_decl!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
295
296// =============================================================================
297// Private module for sealed traits
298// =============================================================================
299
300/// Private module for sealed traits to prevent external implementations.
301mod private {
302    /// Sealed trait to prevent external implementations of [`FunctionDecl`].
303    pub trait Sealed {}
304}
305
306#[cfg(test)]
307mod tests {
308    use super::*;
309
310    #[test]
311    fn test_zero_parameter_function() {
312        // Test function with no parameters
313        type ConstantFn = fn() -> i64;
314
315        assert_eq!(ConstantFn::arguments(), vec![]);
316        assert_eq!(ConstantFn::result(), ValueType::Int);
317    }
318
319    #[test]
320    fn test_single_parameter_function() {
321        // Test function with one parameter
322        type SquareFn = fn(i64) -> i64;
323
324        assert_eq!(SquareFn::arguments(), vec![ValueType::Int]);
325        assert_eq!(SquareFn::result(), ValueType::Int);
326    }
327
328    #[test]
329    fn test_multiple_parameter_function() {
330        // Test function with multiple parameters
331        type AddFn = fn(i64, i64, i64) -> i64;
332
333        assert_eq!(
334            AddFn::arguments(),
335            vec![ValueType::Int, ValueType::Int, ValueType::Int]
336        );
337        assert_eq!(AddFn::result(), ValueType::Int);
338    }
339
340    #[test]
341    fn test_mixed_type_function() {
342        // Test function with mixed argument types
343        type FormatFn = fn(String, i64, bool) -> String;
344
345        assert_eq!(
346            FormatFn::arguments(),
347            vec![ValueType::String, ValueType::Int, ValueType::Bool]
348        );
349        assert_eq!(FormatFn::result(), ValueType::String);
350    }
351
352    #[test]
353    fn test_string_function() {
354        // Test function with string types
355        type ConcatFn = fn(String, String) -> String;
356
357        assert_eq!(
358            ConcatFn::arguments(),
359            vec![ValueType::String, ValueType::String]
360        );
361        assert_eq!(ConcatFn::result(), ValueType::String);
362    }
363
364    #[test]
365    fn test_floating_point_function() {
366        // Test function with floating point types
367        type MathFn = fn(f64, f64) -> f64;
368
369        assert_eq!(
370            MathFn::arguments(),
371            vec![ValueType::Double, ValueType::Double]
372        );
373        assert_eq!(MathFn::result(), ValueType::Double);
374    }
375
376    #[test]
377    fn test_boolean_function() {
378        // Test function with boolean types
379        type LogicFn = fn(bool, bool) -> bool;
380
381        assert_eq!(LogicFn::arguments(), vec![ValueType::Bool, ValueType::Bool]);
382        assert_eq!(LogicFn::result(), ValueType::Bool);
383    }
384
385    #[test]
386    fn test_maximum_parameters() {
387        // Test function with maximum supported parameters (10)
388        type MaxParamFn = fn(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64) -> i64;
389
390        let expected_args = vec![ValueType::Int; 10];
391        assert_eq!(MaxParamFn::arguments(), expected_args);
392        assert_eq!(MaxParamFn::result(), ValueType::Int);
393    }
394}