|
15 | 15 | //! Support for lenses, a way of focusing on subfields of data.
|
16 | 16 |
|
17 | 17 | use std::marker::PhantomData;
|
| 18 | +use std::ops; |
18 | 19 |
|
19 | 20 | pub use druid_derive::Lens;
|
20 | 21 |
|
@@ -252,3 +253,82 @@ impl<T: Clone, U: Clone, B> Clone for Then<T, U, B> {
|
252 | 253 | }
|
253 | 254 | }
|
254 | 255 | }
|
| 256 | + |
| 257 | +#[derive(Debug, Copy, Clone)] |
| 258 | +pub struct Deref; |
| 259 | + |
| 260 | +impl<T: ?Sized> Lens<T, T::Target> for Deref |
| 261 | +where T: ops::Deref + ops::DerefMut, |
| 262 | +{ |
| 263 | + fn with<V, F: FnOnce(&T::Target) -> V>(&self, data: &T, f: F) -> V { |
| 264 | + f(data.deref()) |
| 265 | + } |
| 266 | + fn with_mut<V, F: FnOnce(&mut T::Target) -> V>(&self, data: &mut T, f: F) -> V { |
| 267 | + f(data.deref_mut()) |
| 268 | + } |
| 269 | +} |
| 270 | + |
| 271 | +/// `Lens` for indexing containers |
| 272 | +#[derive(Debug, Copy, Clone)] |
| 273 | +pub struct Index<I> { |
| 274 | + index: I, |
| 275 | +} |
| 276 | + |
| 277 | +impl<I> Index<I> { |
| 278 | + /// Construct a lens that accesses a particular index |
| 279 | + /// |
| 280 | + /// See also `LensExt::index`. |
| 281 | + pub fn new(index: I) -> Self { |
| 282 | + Self { index } |
| 283 | + } |
| 284 | +} |
| 285 | + |
| 286 | +impl<T, I> Lens<T, T::Output> for Index<I> |
| 287 | +where |
| 288 | + T: ?Sized + ops::Index<I> + ops::IndexMut<I>, |
| 289 | + I: Clone, |
| 290 | +{ |
| 291 | + fn with<V, F: FnOnce(&T::Output) -> V>(&self, data: &T, f: F) -> V { |
| 292 | + f(&data[self.index.clone()]) |
| 293 | + } |
| 294 | + fn with_mut<V, F: FnOnce(&mut T::Output) -> V>(&self, data: &mut T, f: F) -> V { |
| 295 | + f(&mut data[self.index.clone()]) |
| 296 | + } |
| 297 | +} |
| 298 | + |
| 299 | +pub trait Iso<A, B> { |
| 300 | + fn forward_ref(&self, a: &A) -> B; |
| 301 | + fn reverse_ref(&self, b: &B) -> A; |
| 302 | + |
| 303 | + fn forward(&self, a: A) -> B { |
| 304 | + self.forward_ref(&a) |
| 305 | + } |
| 306 | + |
| 307 | + fn reverse(&self, b: B) -> A { |
| 308 | + self.reverse_ref(&b) |
| 309 | + } |
| 310 | + |
| 311 | + fn into_lens(self) -> IsoLens<Self> |
| 312 | + where Self: Sized |
| 313 | + { |
| 314 | + IsoLens { iso: self } |
| 315 | + } |
| 316 | +} |
| 317 | + |
| 318 | +#[derive(Debug, Copy, Clone)] |
| 319 | +pub struct IsoLens<I> { |
| 320 | + iso: I, |
| 321 | +} |
| 322 | + |
| 323 | +impl<A, B, I: Iso<A, B>> Lens<A, B> for IsoLens<I> { |
| 324 | + fn with<T, F: FnOnce(&B) -> T>(&self, data: &A, f: F) -> T { |
| 325 | + f(&self.iso.forward_ref(data)) |
| 326 | + } |
| 327 | + |
| 328 | + fn with_mut<T, F: FnOnce(&mut B) -> T>(&self, data: &mut A, f: F) -> T { |
| 329 | + let mut x = self.iso.forward_ref(data); |
| 330 | + let v = f(&mut x); |
| 331 | + *data = self.iso.reverse(x); |
| 332 | + v |
| 333 | + } |
| 334 | +} |
0 commit comments