1use super::{Compose, Identity, Invert, Iso, Lenticuloid, util};
2
3pub type Injector<'l, X, Y> = Box<FnMut(X) -> Option<Y> + 'l>;
4
5pub 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 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}