Skip to main content

filt_rs/functions/
macros.rs

1/// Defines a function type with the given name and argument names, implementing
2/// [`crate::Function`] with the provided body.
3///
4/// The body may refer to the arguments by name, and must return a
5/// [`std::borrow::Cow<FilterValue>`]. The body is evaluated each time the function is called, and may
6/// borrow from the arguments, but must not retain references to them beyond the
7/// lifetime of the returned value.
8///
9/// ## Example
10/// ```rust
11/// use filt_rs::{function, FilterValue};
12/// use std::borrow::Cow;
13///
14/// function!{
15///     /// Calculates the length of a string argument, returning a number.
16///     len(s) {
17///         match s.as_ref() {
18///             FilterValue::String(s) => Cow::Owned(FilterValue::Number(s.chars().count() as f64)),
19///             _ => Cow::Owned(FilterValue::Null),
20///         }
21///     }
22/// }
23/// ```
24#[macro_export]
25macro_rules! function {
26    ($(#[$outer:meta])* $ty:ident ( $($arg:ident),* ) $body:block) => {
27        #[allow(non_camel_case_types)]
28        $(#[$outer])*
29        pub(crate) struct $ty;
30
31        impl $crate::Function for $ty {
32            fn name(&self) -> &str {
33                stringify!($ty)
34            }
35
36            fn arity(&self) -> usize {
37                function!(!count $($arg)*)
38            }
39
40            fn call<'a>(&self, args: &[::std::borrow::Cow<'a, $crate::FilterValue<'a>>]) -> ::std::borrow::Cow<'a, $crate::FilterValue<'a>> {
41                #[allow(unused_variables, unused_mut)]
42                let mut iter = args.iter();
43                $(let $arg = iter.next().unwrap();)*
44                $body
45            }
46        }
47    };
48
49    (!count $x:tt $($xs:tt)*) => {
50        1usize $(+ function!(!count $xs))*
51    };
52
53    (!count) => {
54        0usize
55    };
56}