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}