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);