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}