refraction/
partial_lens.rs

1use super::{Compose, Identity, Invert, Iso, Lenticuloid, util};
2
3pub type Injector<'l, X, Y> = Box<FnMut(X) -> Option<Y> + 'l>;
4
5/// The supertype of all partial lens families.
6pub trait PartialLens: Lenticuloid
7    where Self::AtInitial: PartialLens,
8          Self::AtFinal: PartialLens
9{
10    fn try_get(&self, v: Self::InitialSource) -> Result<Self::InitialTarget, Self::FinalSource> {
11        self.try_get_inject(v).map(|(x, _)| x)
12    }
13
14    /// This signature is somewhat hacky; it awaits resolution of the `FnBox`
15    /// issue for better design. Notably, the injection function returned by
16    /// this method will (if law-abiding) only return `Some` exactly once;
17    /// every time afterwards, it will return `None`.
18    fn try_get_inject(&self,
19                      v: Self::InitialSource)
20                      -> Result<(Self::InitialTarget,
21                                 Injector<Self::FinalTarget, Self::FinalSource>),
22                                Self::FinalSource>;
23
24    fn set(&self, v: Self::InitialSource, x: Self::FinalTarget) -> Self::FinalSource {
25        self.modify(v, |_| x)
26    }
27
28    fn exchange(&self,
29                v: Self::InitialSource,
30                x: Self::FinalTarget)
31                -> (Option<Self::InitialTarget>, Self::FinalSource) {
32        let (a, b) = self.modify_with(v, |y| (x, y));
33        (b, a)
34    }
35
36    fn modify<F>(&self, v: Self::InitialSource, f: F) -> Self::FinalSource
37        where F: FnOnce(Self::InitialTarget) -> Self::FinalTarget
38    {
39        self.modify_with(v, |x| (f(x), ())).0
40    }
41
42    fn modify_with<F, X>(&self, v: Self::InitialSource, f: F) -> (Self::FinalSource, Option<X>)
43        where F: FnOnce(Self::InitialTarget) -> (Self::FinalTarget, X);
44}
45
46impl<S, T> PartialLens for Identity<S, T> {
47    #[inline]
48    fn try_get(&self, v: S) -> Result<S, T> {
49        Ok(v)
50    }
51
52    #[inline]
53    fn try_get_inject(&self, v: S) -> Result<(S, Injector<T, T>), T> {
54        Ok((v, util::once_to_mut(|x| x)))
55    }
56
57    #[inline]
58    fn set(&self, _v: S, x: T) -> T {
59        x
60    }
61
62    #[inline]
63    fn exchange(&self, v: S, x: T) -> (Option<S>, T) {
64        (Some(v), x)
65    }
66
67    #[inline]
68    fn modify<F: FnOnce(S) -> T>(&self, v: S, f: F) -> T {
69        f(v)
70    }
71
72    #[inline]
73    fn modify_with<F: FnOnce(S) -> (T, X), X>(&self, v: S, f: F) -> (T, Option<X>) {
74        let (a, b) = f(v);
75        (a, Some(b))
76    }
77}
78
79impl<LF: PartialLens, LS: ?Sized> PartialLens for Compose<LF, LS>
80    where LS: PartialLens<InitialTarget = LF::InitialSource, FinalTarget = LF::FinalSource>,
81          LF::AtInitial: PartialLens,
82          LF::AtFinal: PartialLens,
83          LS::AtInitial: PartialLens,
84          LS::AtFinal: PartialLens
85{
86    fn try_get(&self, v: Self::InitialSource) -> Result<Self::InitialTarget, Self::FinalSource> {
87        let Compose { first: ref lf, second: ref ls } = *self;
88        ls.try_get_inject(v).and_then(move |(q, mut inj)| {
89            lf.try_get(q).map_err(move |x| inj(x).unwrap_or_else(|| unreachable!()))
90        })
91    }
92
93    fn try_get_inject(&self,
94                      v: Self::InitialSource)
95                      -> Result<(Self::InitialTarget,
96                                 Injector<Self::FinalTarget, Self::FinalSource>),
97                                Self::FinalSource> {
98        let Compose { first: ref lf, second: ref ls } = *self;
99        ls.try_get_inject(v).and_then(move |(q, mut inj_q)| {
100            let res = lf.try_get_inject(q).map(|(x, mut inj_x)| {
101                (x, move |y| inj_x(y).unwrap_or_else(|| unreachable!()))
102            });
103            match res {
104                Ok((x, mut inj_x)) => {
105                    Ok((x,
106                        util::once_to_mut(move |y| {
107                            inj_q(inj_x(y)).unwrap_or_else(|| unreachable!())
108                        })))
109                }
110                Err(q) => Err(inj_q(q).unwrap_or_else(|| unreachable!())),
111            }
112        })
113    }
114
115    fn set(&self, v: Self::InitialSource, x: Self::FinalTarget) -> Self::FinalSource {
116        self.second.modify(v, |q| self.first.set(q, x))
117    }
118
119    fn exchange(&self,
120                v: Self::InitialSource,
121                x: Self::FinalTarget)
122                -> (Option<Self::InitialTarget>, Self::FinalSource) {
123        let (a, b_opt) = self.second.modify_with(v, |q| {
124            let (c, d) = self.first.exchange(q, x);
125            (d, c)
126        });
127        (b_opt.and_then(|b| b), a)
128    }
129
130    fn modify<F>(&self, v: Self::InitialSource, f: F) -> Self::FinalSource
131        where F: FnOnce(Self::InitialTarget) -> Self::FinalTarget
132    {
133        self.second.modify(v, |q| self.first.modify(q, f))
134    }
135
136    fn modify_with<F, X>(&self, v: Self::InitialSource, f: F) -> (Self::FinalSource, Option<X>)
137        where F: FnOnce(Self::InitialTarget) -> (Self::FinalTarget, X)
138    {
139        let (a, b_opt) = self.second.modify_with(v, |q| self.first.modify_with(q, f));
140        (a, b_opt.and_then(|b| b))
141    }
142}
143
144impl<L: Iso> PartialLens for Invert<L>
145    where L::AtInitial: Iso,
146          L::AtFinal: Iso
147{
148    #[inline]
149    fn try_get(&self, v: Self::InitialSource) -> Result<Self::InitialTarget, Self::FinalSource> {
150        Ok(self.deinvert.inject(v))
151    }
152
153    #[inline]
154    fn try_get_inject(&self,
155                      v: Self::InitialSource)
156                      -> Result<(Self::InitialTarget,
157                                 Injector<Self::FinalTarget, Self::FinalSource>),
158                                Self::FinalSource> {
159        Ok((self.deinvert.inject(v), util::once_to_mut(move |x| self.deinvert.get(x))))
160    }
161
162    #[inline]
163    fn set(&self, _v: Self::InitialSource, x: Self::FinalTarget) -> Self::FinalSource {
164        self.deinvert.get(x)
165    }
166
167    #[inline]
168    fn exchange(&self,
169                v: Self::InitialSource,
170                x: Self::FinalTarget)
171                -> (Option<Self::InitialTarget>, Self::FinalSource) {
172        let l = &self.deinvert;
173        (Some(l.inject(v)), l.get(x))
174    }
175
176    #[inline]
177    fn modify<F>(&self, v: Self::InitialSource, f: F) -> Self::FinalSource
178        where F: FnOnce(Self::InitialTarget) -> Self::FinalTarget
179    {
180        let l = &self.deinvert;
181        l.get(f(l.inject(v)))
182    }
183
184    #[inline]
185    fn modify_with<F, X>(&self, v: Self::InitialSource, f: F) -> (Self::FinalSource, Option<X>)
186        where F: FnOnce(Self::InitialTarget) -> (Self::FinalTarget, X)
187    {
188        let l = &self.deinvert;
189        let (x, ret) = f(l.inject(v));
190        (l.get(x), Some(ret))
191    }
192}