fx_rs/core/
handler.rs

1use crate::Fx;
2use dyn_clone::{DynClone, clone_trait_object};
3
4impl<'f, S: Clone, V: Clone> Fx<'f, S, V> {
5    pub fn via<T, U, H>(self, h: H) -> Fx<'f, T, U>
6    where
7        T: Clone,
8        U: Clone,
9        H: Into<Handler<'f, S, T, V, U>>,
10    {
11        h.into().handle(self)
12    }
13}
14
15impl<'f, A: Clone, B: Clone, U: Clone, V: Clone> Handler<'f, A, B, U, V> {
16    pub fn on_left<S: Clone>(self) -> Handler<'f, (A, S), (B, S), U, V> {
17        Handler::new(move |e| e.and_swap().via(self.clone().on_right()).and_swap())
18    }
19
20    pub fn on_right<S: Clone>(self) -> Handler<'f, (S, A), (S, B), U, V> {
21        Handler::new(move |e| e.and_nest().via(self.clone().on_value()).and_flat())
22    }
23
24    pub fn on_value<S: Clone>(self) -> Handler<'f, S, S, Fx<'f, A, U>, Fx<'f, B, V>> {
25        Handler::new(move |e: Fx<'f, S, Fx<'f, A, U>>| {
26            e.flat_map(|i: Fx<'f, A, U>| Fx::func(move |h: Self| h.handle(i.clone())))
27                .and_swap()
28                .provide_left(self.clone())
29        })
30    }
31}
32
33impl<'f, A: Clone, B: Clone, U: Clone, V: Clone> Handler<'f, A, B, U, V> {
34    pub fn new<F>(f: F) -> Self
35    where
36        F: FnOnce(Fx<'f, A, U>) -> Fx<'f, B, V> + Clone + 'f,
37    {
38        Self(Box::new(f))
39    }
40
41    pub fn handle(self, e: Fx<'f, A, U>) -> Fx<'f, B, V> {
42        self.0(e)
43    }
44
45    pub fn clone_boxed(&self) -> Box<dyn FnOnce(Fx<'f, A, U>) -> Fx<'f, B, V> + 'f> {
46        self.0.clone()
47    }
48
49    pub fn contra_map<S, T, H>(self, h: H) -> Handler<'f, S, B, T, V>
50    where
51        H: FnOnce(Fx<'f, S, T>) -> Fx<'f, A, U> + Clone + 'f,
52        S: Clone,
53        T: Clone,
54    {
55        Handler::new(|e| self.handle(h(e)))
56    }
57
58    pub fn map<S, T, H>(self, h: H) -> Handler<'f, A, S, U, T>
59    where
60        H: FnOnce(Fx<'f, B, V>) -> Fx<'f, S, T> + Clone + 'f,
61        S: Clone,
62        T: Clone,
63    {
64        Handler::new(|e| h(self.handle(e)))
65    }
66}
67
68#[derive(Clone)]
69pub struct Handler<'f, A: Clone, B: Clone, U: Clone, V: Clone>(
70    Box<dyn HandlerFn<'f, A, B, U, V> + 'f>,
71);
72
73clone_trait_object!(<'f, A: Clone, B: Clone, U:Clone, V:Clone> HandlerFn<'f, A, B, U, V>);
74trait HandlerFn<'f, A, B, U, V>: DynClone + FnOnce(Fx<'f, A, U>) -> Fx<'f, B, V> + 'f
75where
76    V: Clone + 'f,
77    U: Clone + 'f,
78    A: Clone + 'f,
79    B: Clone + 'f,
80{
81}
82impl<'f, A, B, U, V, F> HandlerFn<'f, A, B, U, V> for F
83where
84    F: FnOnce(Fx<'f, A, U>) -> Fx<'f, B, V> + Clone + 'f,
85    V: Clone + 'f,
86    U: Clone + 'f,
87    A: Clone + 'f,
88    B: Clone + 'f,
89{
90}
91
92impl<'f, A, B, U, V, F> From<F> for Handler<'f, A, B, U, V>
93where
94    F: FnOnce(Fx<'f, A, U>) -> Fx<'f, B, V> + Clone + 'f,
95    V: Clone + 'f,
96    U: Clone + 'f,
97    A: Clone + 'f,
98    B: Clone + 'f,
99{
100    fn from(value: F) -> Self {
101        Handler::new(value)
102    }
103}
104
105impl<'f, A, B, U, V> From<Handler<'f, A, B, U, V>> for Box<dyn HandlerFn<'f, A, B, U, V> + 'f>
106where
107    V: Clone + 'f,
108    U: Clone + 'f,
109    A: Clone + 'f,
110    B: Clone + 'f,
111{
112    fn from(value: Handler<'f, A, B, U, V>) -> Self {
113        value.0
114    }
115}