fx_rs/core/
lens.rs

1use dyn_clone::{DynClone, clone_trait_object};
2
3use crate::{Fx, Handler};
4
5#[derive(Clone)]
6pub struct Lens<'f, Outer: Clone, Inner: Clone>(Get<'f, Outer, Inner>, Set<'f, Outer, Inner>);
7
8impl<'f, Outer: Clone, Inner: Clone> Lens<'f, Outer, Inner> {
9    pub fn new<G, S>(getter: G, setter: S) -> Self
10    where
11        G: FnOnce(Outer) -> Inner + Clone + 'f,
12        S: FnOnce(Outer, Inner) -> Outer + Clone + 'f,
13    {
14        Self(Box::new(getter), Box::new(setter))
15    }
16
17    pub fn zoom_out<V: Clone>(self) -> Handler<'f, Inner, Outer, V, V> {
18        Handler::new(|e| e.contra_map(self.0, self.1))
19    }
20
21    pub fn zoom_in<V: Clone, U: Clone, F>(self, inner: F) -> Handler<'f, Outer, Outer, V, U>
22    where
23        Inner: 'f,
24        U: Clone + 'f,
25        F: FnOnce(V) -> Fx<'f, Inner, U> + Clone + 'f,
26    {
27        Handler::new(|e| e.map_m(|v| inner(v).via(self.zoom_out())))
28    }
29
30    pub fn prepend<LeftOuter: Clone>(
31        self,
32        left: Lens<'f, LeftOuter, Outer>,
33    ) -> Lens<'f, LeftOuter, Inner>
34    where
35        Inner: 'f,
36        LeftOuter: 'f,
37        Outer: 'f,
38    {
39        let reader = (left.0).clone();
40        Lens::<LeftOuter, Inner>::new(
41            |left_outer| self.0(reader(left_outer)),
42            |left_outer, inner| left.1(left_outer.clone(), self.1(left.0(left_outer), inner)),
43        )
44    }
45
46    pub fn append<RightInner: Clone>(
47        self,
48        right: Lens<'f, Inner, RightInner>,
49    ) -> Lens<'f, Outer, RightInner>
50    where
51        Inner: 'f,
52        RightInner: 'f,
53        Outer: 'f,
54    {
55        let reader = (self.0).clone();
56        Lens::<Outer, RightInner>::new(
57            |outer| right.0(reader(outer)),
58            |outer, right_inner| self.1(outer.clone(), right.1(self.0(outer), right_inner)),
59        )
60    }
61}
62
63impl<'f, A: Clone, B: Clone> Lens<'f, (A, B), A> {
64    pub fn left() -> Self {
65        Self::new(|(a, _)| a, |(_, b), a| (a, b))
66    }
67}
68
69impl<'f, A: Clone, B: Clone> Lens<'f, (A, B), B> {
70    pub fn right() -> Self {
71        Self::new(|(_, b)| b, |(a, _), b| (a, b))
72    }
73}
74
75type Get<'f, Outer, Inner> = Box<dyn GetterFn<'f, Outer, Inner> + 'f>;
76
77clone_trait_object!(<'f, Outer:Clone, Inner:Clone> GetterFn<'f, Outer, Inner>);
78trait GetterFn<'f, Outer: Clone, Inner: Clone>
79where
80    Self: DynClone + FnOnce(Outer) -> Inner + 'f,
81{
82}
83
84impl<'f, Outer: Clone, Inner: Clone, F> GetterFn<'f, Outer, Inner> for F where
85    F: FnOnce(Outer) -> Inner + Clone + 'f
86{
87}
88
89type Set<'f, Outer, Inner> = Box<dyn SetterFn<'f, Outer, Inner> + 'f>;
90
91clone_trait_object!(<'f, Outer:Clone, Inner:Clone> SetterFn<'f, Outer, Inner>);
92trait SetterFn<'f, Outer: Clone, Inner: Clone>
93where
94    Self: DynClone + FnOnce(Outer, Inner) -> Outer + 'f,
95{
96}
97
98impl<'f, Outer: Clone, Inner: Clone, F> SetterFn<'f, Outer, Inner> for F where
99    F: FnOnce(Outer, Inner) -> Outer + Clone + 'f
100{
101}