1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#[macro_export]
macro_rules! impl_conversions {
    // Capture pairs separated by commas, where each pair is separated by =>
    ($($target_type:ty => $value_variant:path),* $(,)?) => {
        $(
            impl FromValue for $target_type {
                fn from_value(expr: &Value) -> Result<Self, ExecutionError> {
                    if let $value_variant(v) = expr {
                        Ok(v.clone())
                    } else {
                        Err(ExecutionError::UnexpectedType {
                            got: format!("{:?}", expr),
                            want: stringify!($target_type).to_string(),
                        })
                    }
                }
            }

            impl FromValue for Option<$target_type> {
                fn from_value(expr: &Value) -> Result<Self, ExecutionError> {
                    match expr {
                        Value::Null => Ok(None),
                        $value_variant(v) => Ok(Some(v.clone())),
                        _ => Err(ExecutionError::UnexpectedType {
                            got: format!("{:?}", expr),
                            want: stringify!($target_type).to_string(),
                        }),
                    }
                }
            }

            impl From<$target_type> for Value {
                fn from(value: $target_type) -> Self {
                    $value_variant(value)
                }
            }

            impl crate::magic::IntoResolveResult for $target_type {
                fn into_resolve_result(self) -> ResolveResult {
                    Ok($value_variant(self))
                }
            }

            impl crate::magic::IntoResolveResult for Result<$target_type, ExecutionError> {
                fn into_resolve_result(self) -> ResolveResult {
                    self.map($value_variant)
                }
            }

            impl<'a, 'context> FromContext<'a, 'context> for $target_type {
                fn from_context(ctx: &'a mut FunctionContext<'context>) -> Result<Self, ExecutionError>
                where
                    Self: Sized,
                {
                    arg_value_from_context(ctx).and_then(|v| FromValue::from_value(&v))
                }
            }
        )*
    }
}

#[macro_export]
macro_rules! impl_handler {
    ($($t:ty),*) => {
        paste::paste! {
            impl<F, $($t,)* R> Handler<($($t,)*)> for F
            where
                F: Fn($($t,)*) -> R + Clone,
                $($t: for<'a, 'context> crate::FromContext<'a, 'context>,)*
                R: IntoResolveResult,
            {
                fn call(self, _ftx: &mut FunctionContext) -> ResolveResult {
                    $(
                        let [<arg_ $t:lower>] = $t::from_context(_ftx)?;
                    )*
                    self($([<arg_ $t:lower>],)*).into_resolve_result()
                }
            }

            impl<F, $($t,)* R> Handler<(WithFunctionContext, $($t,)*)> for F
            where
                F: Fn(&FunctionContext, $($t,)*) -> R + Clone,
                $($t: for<'a, 'context> crate::FromContext<'a, 'context>,)*
                R: IntoResolveResult,
            {
                fn call(self, _ftx: &mut FunctionContext) -> ResolveResult {
                    $(
                        let [<arg_ $t:lower>] = $t::from_context(_ftx)?;
                    )*
                    self(_ftx, $([<arg_ $t:lower>],)*).into_resolve_result()
                }
            }
        }
    };
}

pub(crate) use impl_conversions;
pub(crate) use impl_handler;