1use std::any::Any;
7use std::marker::PhantomData;
8
9use crate::BoxedArguments;
10use crate::TestDsl;
11use crate::argument::ParseArguments;
12use crate::argument::VerbArgument;
13use crate::error::TestErrorCase;
14
15pub trait Verb<H>: std::fmt::Debug + Clone + 'static {
17 type Arguments: ParseArguments<H>;
19
20 fn run(&self, harness: &mut H, arguments: &Self::Arguments) -> miette::Result<()>;
22}
23
24pub(crate) struct ErasedVerb<H> {
25 verb: Box<dyn Any>,
26 fn_parse_args:
27 fn(&crate::TestDsl<H>, &kdl::KdlNode) -> Result<Box<dyn BoxedArguments<H>>, TestErrorCase>,
28 fn_run: fn(&dyn Any, &mut H, &dyn Any) -> miette::Result<()>,
29 fn_clone: fn(&dyn Any) -> Box<dyn Any>,
30}
31
32impl<H> std::fmt::Debug for ErasedVerb<H> {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 f.debug_struct("ErasedVerb")
35 .field("verb", &self.verb)
36 .field("fn_parse_args", &self.fn_parse_args)
37 .field("fn_run", &self.fn_run)
38 .field("fn_clone", &self.fn_clone)
39 .finish()
40 }
41}
42
43impl<H> Clone for ErasedVerb<H> {
44 fn clone(&self) -> Self {
45 Self {
46 verb: (self.fn_clone)(&*self.verb),
47 fn_parse_args: self.fn_parse_args,
48 fn_run: self.fn_run,
49 fn_clone: self.fn_clone,
50 }
51 }
52}
53
54impl<H> ErasedVerb<H> {
55 pub(crate) fn erase<V>(verb: V) -> Self
56 where
57 V: Verb<H>,
58 {
59 ErasedVerb {
60 verb: Box::new(verb),
61 fn_parse_args: |test_dsl, node| {
62 <V::Arguments as ParseArguments<H>>::parse(test_dsl, node).map(|a| {
63 let args = Box::new(a);
64 args as _
65 })
66 },
67 fn_run: |this, harness, arguments| {
68 let this: &V = this.downcast_ref().unwrap();
69 let arguments: &V::Arguments = arguments.downcast_ref().unwrap();
70
71 this.run(harness, arguments)
72 },
73 fn_clone: |this| {
74 let this: &V = this.downcast_ref().unwrap();
75
76 Box::new(this.clone())
77 },
78 }
79 }
80
81 pub(crate) fn parse_args(
82 &self,
83 test_dsl: &TestDsl<H>,
84 node: &kdl::KdlNode,
85 ) -> Result<Box<dyn BoxedArguments<H>>, TestErrorCase> {
86 (self.fn_parse_args)(test_dsl, node)
87 }
88
89 pub(crate) fn run(&self, harness: &mut H, arguments: &dyn Any) -> miette::Result<()> {
90 (self.fn_run)(&*self.verb, harness, arguments)
91 }
92}
93
94pub struct FunctionVerb<H, T> {
98 func: BoxedCallable<H, T>,
99 _pd: PhantomData<fn(H, T)>,
100}
101
102impl<H, T> std::fmt::Debug for FunctionVerb<H, T> {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 f.debug_struct("FunctionVerb")
105 .field("func", &self.func)
106 .field("_pd", &self._pd)
107 .finish()
108 }
109}
110
111impl<H, T> Clone for FunctionVerb<H, T> {
112 fn clone(&self) -> Self {
113 Self {
114 func: self.func.clone(),
115 _pd: self._pd,
116 }
117 }
118}
119
120impl<H, T> FunctionVerb<H, T> {
121 pub fn new<F>(func: F) -> Self
123 where
124 F: CallableVerb<H, T>,
125 {
126 FunctionVerb {
127 func: BoxedCallable::new(func),
128 _pd: PhantomData,
129 }
130 }
131}
132
133struct BoxedCallable<H, T> {
134 callable: Box<dyn Any>,
135 call_fn: fn(&dyn Any, &mut H, &T) -> miette::Result<()>,
136 clone_fn: fn(&dyn Any) -> Box<dyn Any>,
137}
138
139impl<H, T> std::fmt::Debug for BoxedCallable<H, T> {
140 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141 f.debug_struct("BoxedCallable")
142 .field("callable", &self.callable)
143 .field("call_fn", &self.call_fn)
144 .field("clone_fn", &self.clone_fn)
145 .finish()
146 }
147}
148
149impl<H, T> Clone for BoxedCallable<H, T> {
150 fn clone(&self) -> Self {
151 BoxedCallable {
152 callable: (self.clone_fn)(&*self.callable),
153 call_fn: self.call_fn,
154 clone_fn: self.clone_fn,
155 }
156 }
157}
158
159impl<H, T> BoxedCallable<H, T> {
160 fn new<F>(callable: F) -> Self
161 where
162 F: CallableVerb<H, T>,
163 {
164 BoxedCallable {
165 callable: Box::new(callable),
166 call_fn: |this, harness, node| {
167 let this: &F = this.downcast_ref().unwrap();
168 this.call(harness, node)
169 },
170 clone_fn: |this| {
171 let this: &F = this.downcast_ref().unwrap();
172 Box::new(this.clone())
173 },
174 }
175 }
176
177 fn call(&self, harness: &mut H, args: &T) -> miette::Result<()> {
178 (self.call_fn)(&*self.callable, harness, args)
179 }
180}
181
182pub trait CallableVerb<H, T>: Clone + 'static {
186 fn call(&self, harness: &mut H, node: &T) -> miette::Result<()>;
188}
189
190impl<H, F, A> CallableVerb<H, ((), A)> for F
191where
192 F: Fn(&mut H, ((), A)) -> miette::Result<()>,
193 F: Clone + 'static,
194 A: ParseArguments<H>,
195{
196 fn call(&self, harness: &mut H, node: &((), A)) -> miette::Result<()> {
197 self(harness, node.clone())
198 }
199}
200
201impl<H, F> CallableVerb<H, ((),)> for F
202where
203 F: Fn(&mut H) -> miette::Result<()>,
204 F: Clone + 'static,
205{
206 fn call(&self, harness: &mut H, _node: &((),)) -> miette::Result<()> {
207 self(harness)
208 }
209}
210
211macro_rules! impl_callable {
212 (
213 [$($ty:ident),*], $last:ident
214 ) => {
215 #[allow(non_snake_case, unused_mut)]
216 impl<H, F, $($ty,)* $last> CallableVerb<H, ($($ty,)* $last,)> for F
217 where
218 F: Fn(&mut H, $($ty,)* $last,) -> miette::Result<()>,
219 F: Clone + 'static,
220 $( $ty: VerbArgument, )*
221 $last: VerbArgument,
222 {
223 fn call(&self, harness: &mut H, arguments: &($($ty,)* $last,)) -> miette::Result<()> {
224 let ($($ty,)* $last,) = arguments.clone();
225 self(harness, $($ty,)* $last,)
226 }
227 }
228 };
229}
230
231all_the_tuples!(impl_callable);
232
233impl<T, H: 'static> Verb<H> for FunctionVerb<H, T>
234where
235 T: ParseArguments<H>,
236{
237 type Arguments = T;
238 fn run(&self, harness: &mut H, args: &T) -> miette::Result<()> {
239 self.func.call(harness, args)
240 }
241}