1use dyn_clone::{DynClone, clone_trait_object};
2
3use super::Fx;
4
5#[derive(Clone)]
6pub struct Ability<'f, I, S, O>(Box<dyn AbilityFn<'f, I, S, O> + 'f>)
8where
9 S: Clone,
10 O: Clone;
11
12clone_trait_object!(<'f, I: Clone + 'f, S: Clone + 'f, O: Clone + 'f> AbilityFn<'f, I, S, O>);
13pub trait AbilityFn<'f, I: Clone + 'f, S: Clone + 'f, O: Clone + 'f>:
14 DynClone + FnOnce(I) -> Fx<'f, S, O> + 'f
15{
16}
17
18impl<'f, I: Clone + 'f, S: Clone + 'f, O: Clone + 'f, F> AbilityFn<'f, I, S, O> for F where
19 F: FnOnce(I) -> Fx<'f, S, O> + Clone + 'f
20{
21}
22
23impl<'f, I: Clone + 'f, S: Clone + 'f, O: Clone + 'f, F> From<F> for Ability<'f, I, S, O>
24where
25 F: FnOnce(I) -> Fx<'f, S, O> + Clone + 'f,
26{
27 fn from(value: F) -> Self {
28 Ability::new(value)
29 }
30}
31
32impl<'f, I: Clone + 'f, S: Clone + 'f, O: Clone + 'f> From<Ability<'f, I, S, O>>
33 for Box<dyn AbilityFn<'f, I, S, O> + 'f>
34{
35 fn from(value: Ability<'f, I, S, O>) -> Self {
36 value.0
37 }
38}
39
40impl<'f, I, S, O> Ability<'f, I, S, O>
41where
42 S: Clone,
43 O: Clone,
44 I: Clone,
45{
46 pub fn new<F>(f: F) -> Self
47 where
48 F: FnOnce(I) -> Fx<'f, S, O> + Clone + 'f,
49 {
50 Self(Box::new(f))
51 }
52
53 pub fn apply(self, i: I) -> Fx<'f, S, O> {
54 self.0(i)
55 }
56
57 pub fn clone_boxed(&self) -> Box<dyn FnOnce(I) -> Fx<'f, S, O> + 'f> {
58 self.0.clone()
59 }
60}