1use crate::{AnyFn, Ref, RefMut, Value};
2use alloc::{boxed::Box, vec};
3use core::any::{Any, TypeId};
4
5pub trait IntoAnyFn<'a, T, S> {
8 fn into_any_fn(self) -> AnyFn<'a>;
10}
11
12macro_rules! impl_function {
13 ([$($name:ident),*], [$([$($trait:tt),*]),*], [$($parameter:ty),*], [$($argument:item),*], [$($type:ty),*]) => {
14 #[allow(unused_parens)]
15 impl<'a, T1: FnMut($($parameter),*) -> T2 + 'a, T2: Any, $($name: Any $(+$trait)*),*> IntoAnyFn<'a, ($($type,)*), T2> for T1 {
16 #[allow(non_snake_case)]
17 fn into_any_fn(mut self) -> AnyFn<'a> {
18 #[allow(unused, unused_mut)]
19 AnyFn::new(
20 vec![$(TypeId::of::<$name>()),*],
21 TypeId::of::<T2>(),
22 Box::new(move |arguments: &[&Value]| {
23 let mut iter = 0..;
24 $($argument);*
25 Ok(Value::new(self($($name!(arguments, iter)),*)))
26 }),
27 )
28 }
29 }
30 };
31}
32
33macro_rules! impl_function_combination {
34 ([$($x:ident),*]) => {
35 impl_function_combination!([$($x),*], [], [], [], [], []);
36 };
37 (
38 [$x:ident$(,)? $($y:ident),*],
39 [$($name:ident),* $(,)?],
40 [$([$($trait:tt),* $(,)?]),* $(,)?],
41 [$($parameter:ty),* $(,)?],
42 [$($argument:item),* $(,)?],
43 [$($type:ty),* $(,)?]
44 ) => {
45 impl_function_combination!(
46 [$($y),*],
47 [$x, $($name),*],
48 [[Clone], $([$($trait),*]),*],
49 [$x, $($parameter),*],
50 [
51 macro_rules! $x {
52 ($arguments:ident, $iter:ident) => {
53 $arguments[$iter.next().unwrap_or_default()]
54 .downcast_ref::<$x>()?
55 .clone()
56 };
57 },
58 $($argument),*
59 ],
60 [$x, $($type),*]
61 );
62 impl_function_combination!(
63 [$($y),*],
64 [$x, $($name),*],
65 [[], $([$($trait),*]),*],
66 [&$x, $($parameter),*],
67 [
68 macro_rules! $x {
69 ($arguments:ident, $iter:ident) => {
70 &*($arguments[$iter.next().unwrap_or_default()]
71 .downcast_ref::<$x>()?)
72 };
73 },
74 $($argument),*
75 ],
76 [Ref<$x>, $($type),*]
77 );
78 impl_function_combination!(
79 [$($y),*],
80 [$x, $($name),*],
81 [[], $([$($trait),*]),*],
82 [&mut $x, $($parameter),*],
83 [
84 macro_rules! $x {
85 ($arguments:ident, $iter:ident) => {
86 &mut *($arguments[$iter.next().unwrap_or_default()]
87 .downcast_mut::<$x>()?)
88 };
89 },
90 $($argument),*
91 ],
92 [RefMut<$x>, $($type),*]
93 );
94 };
95 (
96 [],
97 [$($name:ident),* $(,)?],
98 [$([$($trait:tt),* $(,)?]),* $(,)?],
99 [$($parameter:ty),* $(,)?],
100 [$($argument:item),* $(,)?],
101 [$($type:ty),* $(,)?]
102 ) => {
103 impl_function!(
104 [$($name),*],
105 [$([$($trait),*]),*],
106 [$($parameter),*],
107 [$($argument),*],
108 [$($type),*]
109 );
110 }
111}
112
113macro_rules! impl_functions {
114 ($first_type:ident, $($type:ident),*) => {
115 impl_function_combination!([$first_type, $($type),*]);
116 impl_functions!($($type),*);
117 };
118 ($type:ident) => {
119 impl_function_combination!([$type]);
120 impl_function_combination!([]);
121 }
122}
123
124impl_functions!(A, B, C, D, E, F);