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}