pub trait LensExt<A, B>: Lens<A, B>where
A: ?Sized,
B: ?Sized,{
// Provided methods
fn get(&self, data: &A) -> B
where B: Clone { ... }
fn put(&self, data: &mut A, value: B) { ... }
fn then<Other, C>(self, other: Other) -> Then<Self, Other, B>
where Other: Lens<B, C>,
Self: Sized,
C: ?Sized { ... }
fn map<Get, Put, C>(self, get: Get, put: Put) -> Then<Self, Map<Get, Put>, B>
where Get: Fn(&B) -> C,
Put: Fn(&mut B, C),
Self: Sized { ... }
fn deref(self) -> Then<Self, Deref, B>
where B: Deref + DerefMut,
Self: Sized { ... }
fn as_ref<T>(self) -> Then<Self, Ref, B>
where B: AsRef<T> + AsMut<T>,
Self: Sized,
T: ?Sized { ... }
fn index<I>(self, index: I) -> Then<Self, Index<I>, B>
where I: Clone,
B: Index<I> + IndexMut<I>,
Self: Sized { ... }
fn in_arc(self) -> InArc<Self>
where A: Clone,
B: Data,
Self: Sized { ... }
fn not(self) -> Then<Self, Not, B>
where Self: Sized,
B: Into<bool> + Copy,
bool: Into<B> { ... }
}
Expand description
Helpers for manipulating Lens
es
Provided Methods§
fn then<Other, C>(self, other: Other) -> Then<Self, Other, B>where
Other: Lens<B, C>,
Self: Sized,
C: ?Sized,
fn then<Other, C>(self, other: Other) -> Then<Self, Other, B>where Other: Lens<B, C>, Self: Sized, C: ?Sized,
Compose a Lens<A, B>
with a Lens<B, C>
to produce a Lens<A, C>
struct Foo { x: (u32, bool) }
let lens = lens!(Foo, x).then(lens!((u32, bool), 1));
assert_eq!(lens.get(&Foo { x: (0, true) }), true);
fn map<Get, Put, C>(self, get: Get, put: Put) -> Then<Self, Map<Get, Put>, B>where
Get: Fn(&B) -> C,
Put: Fn(&mut B, C),
Self: Sized,
fn map<Get, Put, C>(self, get: Get, put: Put) -> Then<Self, Map<Get, Put>, B>where Get: Fn(&B) -> C, Put: Fn(&mut B, C), Self: Sized,
Combine a Lens<A, B>
with a function that can transform a B
and its inverse.
Useful for cases where the desired value doesn’t physically exist in A
, but can be
computed. For example, a lens like the following might be used to adapt a value with the
range 0-2 for use with a Widget<f64>
like Slider
that has a range of 0-1:
let lens = lens!((bool, f64), 1);
assert_eq!(lens.map(|x| x / 2.0, |x, y| *x = y * 2.0).get(&(true, 2.0)), 1.0);
The computed C
may represent a whole or only part of the original B
.
fn deref(self) -> Then<Self, Deref, B>where
B: Deref + DerefMut,
Self: Sized,
fn deref(self) -> Then<Self, Deref, B>where B: Deref + DerefMut, Self: Sized,
Invoke a type’s Deref
impl
assert_eq!(lens::Identity.deref().get(&Box::new(42)), 42);
fn as_ref<T>(self) -> Then<Self, Ref, B>where
B: AsRef<T> + AsMut<T>,
Self: Sized,
T: ?Sized,
fn as_ref<T>(self) -> Then<Self, Ref, B>where B: AsRef<T> + AsMut<T>, Self: Sized, T: ?Sized,
Invoke a type’s AsRef
and AsMut
impl.
It also allows indexing arrays with the index
lens as shown in the example.
This is necessary, because the Index
trait in Rust is only implemented
for slices ([T]
), but not for arrays ([T; N]
).
Examples
Using ref
this works:
use druid::{widget::TextBox, Data, Lens, LensExt, Widget, WidgetExt};
#[derive(Clone, Default, Data, Lens)]
struct State {
data: [String; 2],
}
fn with_ref() -> impl Widget<State> {
TextBox::new().lens(State::data.as_ref().index(1))
}
While this fails:
fn without_ref() -> impl Widget<State> {
// results in: `[std::string::String; 2]` cannot be mutably indexed by `usize`
TextBox::new().lens(State::data.index(1))
}
fn index<I>(self, index: I) -> Then<Self, Index<I>, B>where
I: Clone,
B: Index<I> + IndexMut<I>,
Self: Sized,
fn index<I>(self, index: I) -> Then<Self, Index<I>, B>where I: Clone, B: Index<I> + IndexMut<I>, Self: Sized,
Access an index in a container
assert_eq!(lens::Identity.index(2).get(&vec![0u32, 1, 2, 3]), 2);
fn in_arc(self) -> InArc<Self>where
A: Clone,
B: Data,
Self: Sized,
fn in_arc(self) -> InArc<Self>where A: Clone, B: Data, Self: Sized,
Adapt to operate on the contents of an Arc
with efficient copy-on-write semantics
let lens = lens::Identity.index(2).in_arc();
let mut x = Arc::new(vec![0, 1, 2, 3]);
let original = x.clone();
assert_eq!(lens.get(&x), 2);
lens.put(&mut x, 2);
assert!(Arc::ptr_eq(&original, &x), "no-op writes don't cause a deep copy");
lens.put(&mut x, 42);
assert_eq!(&*x, &[0, 1, 42, 3]);
fn not(self) -> Then<Self, Not, B>where
Self: Sized,
B: Into<bool> + Copy,
bool: Into<B>,
fn not(self) -> Then<Self, Not, B>where Self: Sized, B: Into<bool> + Copy, bool: Into<B>,
A lens that reverses a boolean value
Examples
use druid::LensExt;
#[derive(Lens)]
struct MyThing {
first: bool
}
let lens = MyThing::first.not();
let mut val = MyThing { first: false };
assert_eq!(lens.with(&val, |v| *v), true);
lens.with_mut(&mut val, |v| *v = false);
assert_eq!(val.first, true);