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}