druid/lens/lens.rs
1// Copyright 2019 The Druid Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::marker::PhantomData;
16use std::ops;
17use std::sync::Arc;
18
19use crate::Data;
20
21/// A lens is a datatype that gives access to a part of a larger
22/// data structure.
23///
24/// A simple example of a lens is a field of a struct; in this case,
25/// the lens itself is zero-sized. Another case is accessing an array
26/// element, in which case the lens contains the array index.
27///
28/// The most common way to create `Lens` implementations is to
29/// use [`#[derive(Lens)]`](druid_derive::Lens) to access a struct's
30/// fields, but custom implementations are practical as well.
31///
32/// The name "lens" is inspired by the [Haskell lens] package, which
33/// has generally similar goals. It's likely we'll develop more
34/// sophistication, for example combinators to combine lenses.
35///
36/// [Haskell lens]: http://hackage.haskell.org/package/lens
37pub trait Lens<T: ?Sized, U: ?Sized> {
38 /// Get non-mut access to the field.
39 ///
40 /// Runs the supplied closure with a reference to the data. It's
41 /// structured this way, as opposed to simply returning a reference,
42 /// so that the data might be synthesized on-the-fly by the lens.
43 fn with<V, F: FnOnce(&U) -> V>(&self, data: &T, f: F) -> V;
44
45 /// Get mutable access to the field.
46 ///
47 /// This method is defined in terms of a closure, rather than simply
48 /// yielding a mutable reference, because it is intended to be used
49 /// with value-type data (also known as immutable data structures).
50 /// For example, a lens for an immutable list might be implemented by
51 /// cloning the list, giving the closure mutable access to the clone,
52 /// then updating the reference after the closure returns.
53 fn with_mut<V, F: FnOnce(&mut U) -> V>(&self, data: &mut T, f: F) -> V;
54}
55
56/// Helpers for manipulating `Lens`es
57pub trait LensExt<A: ?Sized, B: ?Sized>: Lens<A, B> {
58 /// Copy the targeted value out of `data`
59 fn get(&self, data: &A) -> B
60 where
61 B: Clone,
62 {
63 self.with(data, |x| x.clone())
64 }
65
66 /// Set the targeted value in `data` to `value`
67 fn put(&self, data: &mut A, value: B)
68 where
69 B: Sized,
70 {
71 self.with_mut(data, |x| *x = value);
72 }
73
74 /// Compose a `Lens<A, B>` with a `Lens<B, C>` to produce a `Lens<A, C>`
75 ///
76 /// ```
77 /// # use druid::*;
78 /// struct Foo { x: (u32, bool) }
79 /// let lens = lens!(Foo, x).then(lens!((u32, bool), 1));
80 /// assert_eq!(lens.get(&Foo { x: (0, true) }), true);
81 /// ```
82 fn then<Other, C>(self, other: Other) -> Then<Self, Other, B>
83 where
84 Other: Lens<B, C> + Sized,
85 C: ?Sized,
86 Self: Sized,
87 {
88 Then::new(self, other)
89 }
90
91 /// Combine a `Lens<A, B>` with a function that can transform a `B` and its inverse.
92 ///
93 /// Useful for cases where the desired value doesn't physically exist in `A`, but can be
94 /// computed. For example, a lens like the following might be used to adapt a value with the
95 /// range 0-2 for use with a `Widget<f64>` like `Slider` that has a range of 0-1:
96 ///
97 /// ```
98 /// # use druid::*;
99 /// let lens = lens!((bool, f64), 1);
100 /// assert_eq!(lens.map(|x| x / 2.0, |x, y| *x = y * 2.0).get(&(true, 2.0)), 1.0);
101 /// ```
102 ///
103 /// The computed `C` may represent a whole or only part of the original `B`.
104 fn map<Get, Put, C>(self, get: Get, put: Put) -> Then<Self, Map<Get, Put>, B>
105 where
106 Get: Fn(&B) -> C,
107 Put: Fn(&mut B, C),
108 Self: Sized,
109 {
110 self.then(Map::new(get, put))
111 }
112
113 /// Invoke a type's `Deref` impl
114 ///
115 /// ```
116 /// # use druid::*;
117 /// assert_eq!(lens::Identity.deref().get(&Box::new(42)), 42);
118 /// ```
119 fn deref(self) -> Then<Self, Deref, B>
120 where
121 B: ops::Deref + ops::DerefMut,
122 Self: Sized,
123 {
124 self.then(Deref)
125 }
126
127 /// Invoke a type's `AsRef` and `AsMut` impl.
128 ///
129 /// It also allows indexing arrays with the [`index`] lens as shown in the example.
130 /// This is necessary, because the `Index` trait in Rust is only implemented
131 /// for slices (`[T]`), but not for arrays (`[T; N]`).
132 ///
133 /// # Examples
134 ///
135 /// Using `ref` this works:
136 ///
137 /// ```
138 /// use druid::{widget::TextBox, Data, Lens, LensExt, Widget, WidgetExt};
139 ///
140 /// #[derive(Clone, Default, Data, Lens)]
141 /// struct State {
142 /// data: [String; 2],
143 /// }
144 ///
145 /// fn with_ref() -> impl Widget<State> {
146 /// TextBox::new().lens(State::data.as_ref().index(1))
147 /// }
148 /// ```
149 ///
150 /// While this fails:
151 ///
152 /// ```compile_fail
153 /// # use druid::*;
154 /// # #[derive(Clone, Default, Data, Lens)]
155 /// # struct State {
156 /// # data: [String; 2],
157 /// # }
158 /// fn without_ref() -> impl Widget<State> {
159 /// // results in: `[std::string::String; 2]` cannot be mutably indexed by `usize`
160 /// TextBox::new().lens(State::data.index(1))
161 /// }
162 /// ```
163 ///
164 /// [`Lens`]: ./trait.Lens.html
165 /// [`index`]: #method.index
166 #[allow(clippy::wrong_self_convention)]
167 fn as_ref<T: ?Sized>(self) -> Then<Self, Ref, B>
168 where
169 B: AsRef<T> + AsMut<T>,
170 Self: Sized,
171 {
172 self.then(Ref)
173 }
174
175 /// Access an index in a container
176 ///
177 /// ```
178 /// # use druid::*;
179 /// assert_eq!(lens::Identity.index(2).get(&vec![0u32, 1, 2, 3]), 2);
180 /// ```
181 fn index<I>(self, index: I) -> Then<Self, Index<I>, B>
182 where
183 I: Clone,
184 B: ops::Index<I> + ops::IndexMut<I>,
185 Self: Sized,
186 {
187 self.then(Index::new(index))
188 }
189
190 /// Adapt to operate on the contents of an `Arc` with efficient copy-on-write semantics
191 ///
192 /// ```
193 /// # use druid::*; use std::sync::Arc;
194 /// let lens = lens::Identity.index(2).in_arc();
195 /// let mut x = Arc::new(vec![0, 1, 2, 3]);
196 /// let original = x.clone();
197 /// assert_eq!(lens.get(&x), 2);
198 /// lens.put(&mut x, 2);
199 /// assert!(Arc::ptr_eq(&original, &x), "no-op writes don't cause a deep copy");
200 /// lens.put(&mut x, 42);
201 /// assert_eq!(&*x, &[0, 1, 42, 3]);
202 /// ```
203 fn in_arc(self) -> InArc<Self>
204 where
205 A: Clone,
206 B: Data,
207 Self: Sized,
208 {
209 InArc::new(self)
210 }
211
212 /// A lens that reverses a boolean value
213 ///
214 /// # Examples
215 ///
216 /// ```
217 /// # use druid::*;
218 /// use druid::LensExt;
219 ///
220 /// #[derive(Lens)]
221 /// struct MyThing {
222 /// first: bool
223 /// }
224 ///
225 /// let lens = MyThing::first.not();
226 /// let mut val = MyThing { first: false };
227 /// assert_eq!(lens.with(&val, |v| *v), true);
228 /// lens.with_mut(&mut val, |v| *v = false);
229 /// assert_eq!(val.first, true);
230 /// ```
231 fn not(self) -> Then<Self, Not, B>
232 where
233 Self: Sized,
234 B: Sized + Into<bool> + Copy,
235 bool: Into<B>,
236 {
237 self.then(Not)
238 }
239}
240
241impl<A: ?Sized, B: ?Sized, T: Lens<A, B>> LensExt<A, B> for T {}
242
243/// Lens accessing a member of some type using accessor functions
244///
245/// See also the `lens` macro.
246///
247/// ```
248/// let lens = druid::lens::Field::new(|x: &Vec<u32>| &x[42], |x| &mut x[42]);
249/// ```
250pub struct Field<Get, GetMut> {
251 get: Get,
252 get_mut: GetMut,
253}
254
255impl<Get, GetMut> Field<Get, GetMut> {
256 /// Construct a lens from a pair of getter functions
257 pub fn new<T: ?Sized, U: ?Sized>(get: Get, get_mut: GetMut) -> Self
258 where
259 Get: Fn(&T) -> &U,
260 GetMut: Fn(&mut T) -> &mut U,
261 {
262 Self { get, get_mut }
263 }
264}
265
266impl<T, U, Get, GetMut> Lens<T, U> for Field<Get, GetMut>
267where
268 T: ?Sized,
269 U: ?Sized,
270 Get: Fn(&T) -> &U,
271 GetMut: Fn(&mut T) -> &mut U,
272{
273 fn with<V, F: FnOnce(&U) -> V>(&self, data: &T, f: F) -> V {
274 f((self.get)(data))
275 }
276
277 fn with_mut<V, F: FnOnce(&mut U) -> V>(&self, data: &mut T, f: F) -> V {
278 f((self.get_mut)(data))
279 }
280}
281
282/// Construct a lens accessing a type's field
283///
284/// This is a convenience macro for constructing `Field` lenses for fields or indexable elements.
285///
286/// ```
287/// struct Foo { x: Bar }
288/// struct Bar { y: [i32; 10] }
289/// let lens = druid::lens!(Foo, x);
290/// let lens = druid::lens!((u32, bool), 1);
291/// let lens = druid::lens!([u8], [4]);
292/// let lens = druid::lens!(Foo, x.y[5]);
293/// ```
294#[macro_export]
295macro_rules! lens {
296 ($ty:ty, [$index:expr]) => {
297 $crate::lens::Field::new::<$ty, _>(move |x| &x[$index], move |x| &mut x[$index])
298 };
299 ($ty:ty, $($field:tt)*) => {
300 $crate::lens::Field::new::<$ty, _>(move |x| &x.$($field)*, move |x| &mut x.$($field)*)
301 };
302}
303
304/// `Lens` composed of two lenses joined together
305#[derive(Debug, Copy)]
306pub struct Then<T, U, B: ?Sized> {
307 left: T,
308 right: U,
309 _marker: PhantomData<B>,
310}
311
312impl<T, U, B: ?Sized> Then<T, U, B> {
313 /// Compose two lenses
314 ///
315 /// See also `LensExt::then`.
316 pub fn new<A: ?Sized, C: ?Sized>(left: T, right: U) -> Self
317 where
318 T: Lens<A, B>,
319 U: Lens<B, C>,
320 {
321 Self {
322 left,
323 right,
324 _marker: PhantomData,
325 }
326 }
327}
328
329impl<T, U, A, B, C> Lens<A, C> for Then<T, U, B>
330where
331 A: ?Sized,
332 B: ?Sized,
333 C: ?Sized,
334 T: Lens<A, B>,
335 U: Lens<B, C>,
336{
337 fn with<V, F: FnOnce(&C) -> V>(&self, data: &A, f: F) -> V {
338 self.left.with(data, |b| self.right.with(b, f))
339 }
340
341 fn with_mut<V, F: FnOnce(&mut C) -> V>(&self, data: &mut A, f: F) -> V {
342 self.left.with_mut(data, |b| self.right.with_mut(b, f))
343 }
344}
345
346impl<T: Clone, U: Clone, B> Clone for Then<T, U, B> {
347 fn clone(&self) -> Self {
348 Self {
349 left: self.left.clone(),
350 right: self.right.clone(),
351 _marker: PhantomData,
352 }
353 }
354}
355
356/// `Lens` built from a getter and a setter
357#[derive(Debug, Copy, Clone)]
358pub struct Map<Get, Put> {
359 get: Get,
360 put: Put,
361}
362
363impl<Get, Put> Map<Get, Put> {
364 /// Construct a mapping
365 ///
366 /// See also `LensExt::map`
367 pub fn new<A: ?Sized, B>(get: Get, put: Put) -> Self
368 where
369 Get: Fn(&A) -> B,
370 Put: Fn(&mut A, B),
371 {
372 Self { get, put }
373 }
374}
375
376impl<A: ?Sized, B, Get, Put> Lens<A, B> for Map<Get, Put>
377where
378 Get: Fn(&A) -> B,
379 Put: Fn(&mut A, B),
380{
381 fn with<V, F: FnOnce(&B) -> V>(&self, data: &A, f: F) -> V {
382 f(&(self.get)(data))
383 }
384
385 fn with_mut<V, F: FnOnce(&mut B) -> V>(&self, data: &mut A, f: F) -> V {
386 let mut temp = (self.get)(data);
387 let x = f(&mut temp);
388 (self.put)(data, temp);
389 x
390 }
391}
392
393/// `Lens` for invoking `Deref` and `DerefMut` on a type.
394///
395/// See also [`LensExt::deref`].
396#[derive(Debug, Copy, Clone)]
397pub struct Deref;
398
399impl<T: ?Sized> Lens<T, T::Target> for Deref
400where
401 T: ops::Deref + ops::DerefMut,
402{
403 fn with<V, F: FnOnce(&T::Target) -> V>(&self, data: &T, f: F) -> V {
404 f(data.deref())
405 }
406 fn with_mut<V, F: FnOnce(&mut T::Target) -> V>(&self, data: &mut T, f: F) -> V {
407 f(data.deref_mut())
408 }
409}
410
411/// [`Lens`] for invoking `AsRef` and `AsMut` on a type.
412///
413/// [`LensExt::as_ref`] offers an easy way to apply this,
414/// as well as more information and examples.
415#[derive(Debug, Copy, Clone)]
416pub struct Ref;
417
418impl<T: ?Sized, U: ?Sized> Lens<T, U> for Ref
419where
420 T: AsRef<U> + AsMut<U>,
421{
422 fn with<V, F: FnOnce(&U) -> V>(&self, data: &T, f: F) -> V {
423 f(data.as_ref())
424 }
425 fn with_mut<V, F: FnOnce(&mut U) -> V>(&self, data: &mut T, f: F) -> V {
426 f(data.as_mut())
427 }
428}
429
430/// `Lens` for indexing containers
431#[derive(Debug, Copy, Clone)]
432pub struct Index<I> {
433 index: I,
434}
435
436impl<I> Index<I> {
437 /// Construct a lens that accesses a particular index
438 ///
439 /// See also `LensExt::index`.
440 pub fn new(index: I) -> Self {
441 Self { index }
442 }
443}
444
445impl<T, I> Lens<T, T::Output> for Index<I>
446where
447 T: ?Sized + ops::Index<I> + ops::IndexMut<I>,
448 I: Clone,
449{
450 fn with<V, F: FnOnce(&T::Output) -> V>(&self, data: &T, f: F) -> V {
451 f(&data[self.index.clone()])
452 }
453 fn with_mut<V, F: FnOnce(&mut T::Output) -> V>(&self, data: &mut T, f: F) -> V {
454 f(&mut data[self.index.clone()])
455 }
456}
457
458/// The identity lens: the lens which does nothing, i.e. exposes exactly
459/// the original value.
460///
461/// Useful for starting a lens combinator chain, or passing to lens-based
462/// interfaces.
463#[derive(Debug, Copy, Clone)]
464pub struct Identity;
465
466impl<A: ?Sized> Lens<A, A> for Identity {
467 fn with<V, F: FnOnce(&A) -> V>(&self, data: &A, f: F) -> V {
468 f(data)
469 }
470
471 fn with_mut<V, F: FnOnce(&mut A) -> V>(&self, data: &mut A, f: F) -> V {
472 f(data)
473 }
474}
475
476/// A `Lens` that exposes data within an `Arc` with copy-on-write semantics
477///
478/// A copy is only made in the event that a different value is written.
479#[derive(Debug, Copy, Clone)]
480pub struct InArc<L> {
481 inner: L,
482}
483
484impl<L> InArc<L> {
485 /// Adapt a lens to operate on an `Arc`
486 ///
487 /// See also `LensExt::in_arc`
488 pub fn new<A, B>(inner: L) -> Self
489 where
490 A: Clone,
491 B: Data,
492 L: Lens<A, B>,
493 {
494 Self { inner }
495 }
496}
497
498impl<A, B, L> Lens<Arc<A>, B> for InArc<L>
499where
500 A: Clone,
501 B: Data,
502 L: Lens<A, B>,
503{
504 fn with<V, F: FnOnce(&B) -> V>(&self, data: &Arc<A>, f: F) -> V {
505 self.inner.with(data, f)
506 }
507
508 fn with_mut<V, F: FnOnce(&mut B) -> V>(&self, data: &mut Arc<A>, f: F) -> V {
509 let mut temp = self.inner.with(data, |x| x.clone());
510 let v = f(&mut temp);
511 if self.inner.with(data, |x| !x.same(&temp)) {
512 self.inner.with_mut(Arc::make_mut(data), |x| *x = temp);
513 }
514 v
515 }
516}
517
518/// A `Lens` that always yields ().
519///
520/// This is useful when you wish to have a display only widget, require a type-erased widget, or
521/// obtain app data out of band and ignore your input. (E.g sub-windows)
522#[derive(Debug, Default, Copy, Clone)]
523pub struct Unit;
524
525impl<T> Lens<T, ()> for Unit {
526 fn with<V, F: FnOnce(&()) -> V>(&self, _data: &T, f: F) -> V {
527 f(&())
528 }
529 fn with_mut<V, F: FnOnce(&mut ()) -> V>(&self, _data: &mut T, f: F) -> V {
530 f(&mut ())
531 }
532}
533
534/// A lens that negates a boolean.
535///
536/// It should usually be created using the `LensExt::not` method.
537#[derive(Debug, Copy, Clone)]
538pub struct Not;
539
540impl<T> Lens<T, bool> for Not
541where
542 T: Into<bool> + Copy,
543 bool: Into<T>,
544{
545 fn with<V, F: FnOnce(&bool) -> V>(&self, data: &T, f: F) -> V {
546 let tmp = !<T as Into<bool>>::into(*data);
547 f(&tmp)
548 }
549 fn with_mut<V, F: FnOnce(&mut bool) -> V>(&self, data: &mut T, f: F) -> V {
550 let mut tmp = !<T as Into<bool>>::into(*data);
551 let out = f(&mut tmp);
552 *data = (!tmp).into();
553 out
554 }
555}
556
557/// A lens that always gives the same value and discards changes.
558#[derive(Debug, Copy, Clone)]
559pub struct Constant<T>(pub T);
560
561impl<A, B: Clone> Lens<A, B> for Constant<B> {
562 fn with<V, F: FnOnce(&B) -> V>(&self, _: &A, f: F) -> V {
563 f(&self.0)
564 }
565 fn with_mut<V, F: FnOnce(&mut B) -> V>(&self, _: &mut A, f: F) -> V {
566 let mut tmp = self.0.clone();
567 f(&mut tmp)
568 }
569}
570
571macro_rules! impl_lens_for_tuple {
572 ($(($Lens:ident, $B:ident, $i:tt)),*) => {
573 #[allow(non_snake_case)]
574 impl<A, $($Lens,)* $($B,)*> Lens<A, ($($B,)*)> for ($($Lens,)*)
575 where
576 $($B: Clone,)*
577 $($Lens: Lens<A, $B>,)*
578 {
579 fn with<V, F: FnOnce(&($($B,)*)) -> V>(&self, data: &A, f: F) -> V {
580 $(let $B = self.$i.with(data, |v| v.clone());)*
581 let tuple = ($($B,)*);
582 f(&tuple)
583 }
584 fn with_mut<V, F: FnOnce(&mut ($($B,)*)) -> V>(&self, data: &mut A, f: F) -> V {
585 $(let $B = self.$i.with(data, |v| v.clone());)*
586 let mut tuple = ($($B,)*);
587 let out = f(&mut tuple);
588 let ($($B,)*) = tuple;
589 $(self.$i.with_mut(data, |v| *v = $B);)*
590 out
591 }
592 }
593 };
594}
595
596impl_lens_for_tuple!((L0, L0B, 0), (L1, L1B, 1));
597impl_lens_for_tuple!((L0, L0B, 0), (L1, L1B, 1), (L2, L2B, 2));
598impl_lens_for_tuple!((L0, L0B, 0), (L1, L1B, 1), (L2, L2B, 2), (L3, L3B, 3));
599impl_lens_for_tuple!(
600 (L0, L0B, 0),
601 (L1, L1B, 1),
602 (L2, L2B, 2),
603 (L3, L3B, 3),
604 (L4, L4B, 4)
605);
606impl_lens_for_tuple!(
607 (L0, L0B, 0),
608 (L1, L1B, 1),
609 (L2, L2B, 2),
610 (L3, L3B, 3),
611 (L4, L4B, 4),
612 (L5, L5B, 5)
613);
614impl_lens_for_tuple!(
615 (L0, L0B, 0),
616 (L1, L1B, 1),
617 (L2, L2B, 2),
618 (L3, L3B, 3),
619 (L4, L4B, 4),
620 (L5, L5B, 5),
621 (L6, L6B, 6)
622);
623impl_lens_for_tuple!(
624 (L0, L0B, 0),
625 (L1, L1B, 1),
626 (L2, L2B, 2),
627 (L3, L3B, 3),
628 (L4, L4B, 4),
629 (L5, L5B, 5),
630 (L6, L6B, 6),
631 (L7, L7B, 7)
632);