vizia_core/binding/
lens.rs

1use std::any::TypeId;
2use std::borrow::Borrow;
3use std::fmt::{Debug, Formatter};
4use std::hash::Hash;
5use std::marker::PhantomData;
6use std::ops::{BitAnd, BitOr, Deref};
7use std::rc::Rc;
8
9use crate::context::{CURRENT, MAPS, MAP_MANAGER};
10
11use super::{MapId, StoreId};
12
13/// A Lens allows the construction of a reference to a piece of some data, e.g. a field of a struct.
14///
15/// When deriving the `Lens` trait on a struct, the derive macro constructs a static type which implements the `Lens` trait for each field.
16/// The `view()` method takes a reference to the struct type as input and outputs a reference to the field.
17/// This provides a way to specify a binding to a specific field of some application data.
18pub trait Lens: 'static + Copy + Debug {
19    type Source;
20    type Target;
21
22    fn view<'a>(&self, source: &'a Self::Source) -> Option<LensValue<'a, Self::Target>>;
23    fn id(&self) -> StoreId {
24        StoreId::Source(TypeId::of::<Self>())
25    }
26}
27
28/// A type returned by `Lens::view()` which contains either a reference to model data or an owned value.
29pub enum LensValue<'a, T> {
30    /// A reference to model or local data
31    Borrowed(&'a T),
32    /// Owned data
33    Owned(T),
34}
35
36impl<T: Clone> Clone for LensValue<'_, T> {
37    fn clone(&self) -> Self {
38        match self {
39            LensValue::Borrowed(v) => LensValue::Borrowed(*v),
40            LensValue::Owned(v) => LensValue::Owned(v.clone()),
41        }
42    }
43}
44
45impl<T: Copy> Copy for LensValue<'_, T> {}
46
47impl<T: Clone> LensValue<'_, T> {
48    pub fn into_owned(self) -> T {
49        match self {
50            LensValue::Borrowed(t) => t.clone(),
51            LensValue::Owned(t) => t,
52        }
53    }
54}
55
56impl<T> AsRef<T> for LensValue<'_, T> {
57    fn as_ref(&self) -> &T {
58        self
59    }
60}
61
62impl<B> Deref for LensValue<'_, B>
63where
64    B: Borrow<B>,
65{
66    type Target = B;
67
68    fn deref(&self) -> &B {
69        match *self {
70            LensValue::Borrowed(borrowed) => borrowed,
71            LensValue::Owned(ref owned) => owned.borrow(),
72        }
73    }
74}
75
76/// Helpers for constructing more complex `Lens`es.
77pub trait LensExt: Lens {
78    fn or<Other>(self, other: Other) -> OrLens<Self, Other>
79    where
80        Other: Lens<Target = bool>,
81        Self: Lens<Target = bool>,
82    {
83        OrLens::new(self, other)
84    }
85
86    fn and<Other>(self, other: Other) -> AndLens<Self, Other>
87    where
88        Other: Lens<Target = bool>,
89        Self: Lens<Target = bool>,
90    {
91        AndLens::new(self, other)
92    }
93
94    /// Used to construct a lens to some data contained within some other lensed data.
95    ///
96    /// # Example
97    /// Binds a label to `other_data`, which is a field of a struct `SomeData`, which is a field of the root `AppData` model:
98    /// ```compile_fail
99    /// Binding::new(cx, AppData::some_data.then(SomeData::other_data), |cx, data|{
100    ///
101    /// });
102    /// ```
103    fn then<Other>(self, other: Other) -> Then<Self, Other>
104    where
105        Other: Lens<Source = Self::Target>,
106    {
107        Then::new(self, other)
108    }
109
110    fn idx<T>(self, index: usize) -> Index<Self, T>
111    where
112        T: 'static,
113        Self::Target: Deref<Target = [T]>,
114    {
115        Index::new(self, index)
116    }
117
118    fn map<O: 'static, F: 'static + Fn(&Self::Target) -> O>(self, map: F) -> Map<Self, O> {
119        let id = MAP_MANAGER.with_borrow_mut(|f| f.create());
120        let entity = CURRENT.with_borrow(|f| *f);
121        MAPS.with_borrow_mut(|f| {
122            f.insert(id, (entity, Box::new(MapState { closure: Rc::new(map) })))
123        });
124        Map { id, lens: self, o: PhantomData }
125    }
126
127    fn map_ref<O: 'static, F: 'static + Fn(&Self::Target) -> &O>(self, map: F) -> MapRef<Self, O> {
128        let id = MAP_MANAGER.with_borrow_mut(|f| f.create());
129        let entity = CURRENT.with_borrow(|f| *f);
130        MAPS.with_borrow_mut(|f| {
131            f.insert(id, (entity, Box::new(MapRefState { closure: Rc::new(map) })))
132        });
133        MapRef { id, lens: self, o: PhantomData }
134    }
135
136    fn unwrap<T: 'static>(self) -> Then<Self, UnwrapLens<T>>
137    where
138        Self: Lens<Target = Option<T>>,
139    {
140        self.then(UnwrapLens::new())
141    }
142
143    fn into_lens<T: 'static>(self) -> Then<Self, IntoLens<Self::Target, T>>
144    where
145        Self::Target: Clone + Into<T>,
146    {
147        self.then(IntoLens::new())
148    }
149}
150
151// Implement LensExt for all types which implement Lens.
152impl<T: Lens> LensExt for T {}
153
154pub struct MapState<T, O> {
155    closure: Rc<dyn Fn(&T) -> O>,
156}
157
158pub struct MapRefState<T, O> {
159    closure: Rc<dyn Fn(&T) -> &O>,
160}
161
162pub struct Map<L: Lens, O> {
163    id: MapId,
164    lens: L,
165    o: PhantomData<O>,
166}
167
168impl<L: Lens, O: 'static> Copy for Map<L, O> {}
169
170impl<L: Lens, O: 'static> Clone for Map<L, O> {
171    fn clone(&self) -> Self {
172        *self
173    }
174}
175
176impl<L: Lens, O: 'static> Lens for Map<L, O> {
177    type Source = L::Source;
178    type Target = O;
179
180    fn view<'a>(&self, source: &'a Self::Source) -> Option<LensValue<'a, Self::Target>> {
181        let target = self.lens.view(source)?;
182        let closure = MAPS.with_borrow(|f| {
183            let (_, any) = f.get(&self.id)?;
184            let MapState { closure } = any.downcast_ref()?;
185            Some(closure.clone())
186        })?;
187        Some(LensValue::Owned(closure(&*target)))
188    }
189
190    fn id(&self) -> StoreId {
191        StoreId::Map(self.id.0)
192    }
193}
194
195impl<L: Lens, O: 'static> Debug for Map<L, O> {
196    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
197        f.write_fmt(format_args!("{:?}.map(?)", self.lens))
198    }
199}
200
201pub struct MapRef<L: Lens, O> {
202    id: MapId,
203    lens: L,
204    o: PhantomData<O>,
205}
206
207impl<L: Lens, O: 'static> Copy for MapRef<L, O> {}
208
209impl<L: Lens, O: 'static> Clone for MapRef<L, O> {
210    fn clone(&self) -> Self {
211        *self
212    }
213}
214
215impl<L: Lens, O: 'static + Clone> Lens for MapRef<L, O> {
216    type Source = L::Source;
217    type Target = O;
218
219    fn view<'a>(&self, source: &'a Self::Source) -> Option<LensValue<'a, Self::Target>> {
220        let closure = MAPS.with_borrow(|f| {
221            let (_, any) = f.get(&self.id)?;
222            let MapRefState { closure } = any.downcast_ref()?;
223            Some(closure.clone())
224        })?;
225
226        match self.lens.view(source)? {
227            LensValue::Borrowed(target) => Some(LensValue::Borrowed(closure(target))),
228            LensValue::Owned(target) => Some(LensValue::Owned(closure(&target).clone())),
229        }
230    }
231
232    fn id(&self) -> StoreId {
233        StoreId::Map(self.id.0)
234    }
235}
236
237impl<L: Lens, O: 'static> Debug for MapRef<L, O> {
238    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
239        f.write_fmt(format_args!("{:?}.map(?)", self.lens))
240    }
241}
242
243/// `Lens` composed of two lenses joined together
244pub struct Then<A, B> {
245    a: A,
246    b: B,
247}
248
249impl<A, B> Then<A, B> {
250    pub fn new(a: A, b: B) -> Self
251    where
252        A: Lens,
253        B: Lens,
254    {
255        Self { a, b }
256    }
257}
258
259impl<A, B> Lens for Then<A, B>
260where
261    A: Lens,
262    B: Lens<Source = A::Target>,
263{
264    type Source = A::Source;
265    type Target = B::Target;
266
267    fn view<'a>(&self, source: &'a Self::Source) -> Option<LensValue<'a, Self::Target>> {
268        if let Some(val) = self.a.view(source) {
269            let val = match val {
270                LensValue::Borrowed(val) => return self.b.view(val),
271                LensValue::Owned(ref val) => val,
272            };
273            match self.b.view(val) {
274                Some(LensValue::Owned(val)) => return Some(LensValue::Owned(val)),
275                _ => unreachable!(),
276            }
277        }
278
279        None
280    }
281
282    fn id(&self) -> StoreId {
283        StoreId::Recursive((self.a.id(), self.b.id()).into())
284    }
285}
286
287impl<T: Clone, U: Clone> Clone for Then<T, U> {
288    fn clone(&self) -> Self {
289        Self { a: self.a.clone(), b: self.b.clone() }
290    }
291}
292
293impl<A: Lens, B: Lens> Debug for Then<A, B> {
294    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
295        f.write_fmt(format_args!("{:?}.then({:?})", self.a, self.b))
296    }
297}
298
299impl<T: Copy, U: Copy> Copy for Then<T, U> {}
300
301pub struct Index<L, T> {
302    lens: L,
303    index: usize,
304    pt: PhantomData<T>,
305}
306
307impl<L, T> Index<L, T> {
308    pub fn new(lens: L, index: usize) -> Self {
309        Self { lens, index, pt: PhantomData }
310    }
311
312    pub fn idx(&self) -> usize {
313        self.index
314    }
315}
316
317impl<L: Lens, T> Clone for Index<L, T> {
318    fn clone(&self) -> Self {
319        *self
320    }
321}
322
323impl<L: Lens, T> Copy for Index<L, T> {}
324
325impl<L: Lens, T> Debug for Index<L, T> {
326    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
327        f.write_fmt(format_args!("{:?}.index({:?})", self.lens, self.index))
328    }
329}
330
331impl<L, T> Lens for Index<L, T>
332where
333    L: Lens<Target: Deref<Target = [T]>>,
334    T: 'static + Clone,
335{
336    type Source = L::Source;
337    type Target = T;
338
339    fn view<'a>(&self, source: &'a Self::Source) -> Option<LensValue<'a, Self::Target>> {
340        self.lens.view(source).and_then(|v| match v {
341            LensValue::Borrowed(v) => v.get(self.index).map(LensValue::Borrowed),
342            LensValue::Owned(v) => v.get(self.index).cloned().map(LensValue::Owned),
343        })
344    }
345
346    fn id(&self) -> StoreId {
347        StoreId::Index(TypeId::of::<Self>(), self.index)
348    }
349}
350
351pub struct StaticLens<T: 'static> {
352    data: &'static T,
353}
354
355impl<T> Clone for StaticLens<T> {
356    fn clone(&self) -> Self {
357        *self
358    }
359}
360
361impl<T> Copy for StaticLens<T> {}
362
363impl<T> Debug for StaticLens<T> {
364    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
365        f.write_str("Static Lens: ")?;
366        TypeId::of::<T>().fmt(f)?;
367        Ok(())
368    }
369}
370
371impl<T> Lens for StaticLens<T> {
372    type Source = ();
373    type Target = T;
374
375    fn view<'a>(&self, _: &'a Self::Source) -> Option<LensValue<'a, Self::Target>> {
376        Some(LensValue::Borrowed(self.data))
377    }
378}
379
380impl<T> StaticLens<T> {
381    pub fn new(data: &'static T) -> Self {
382        StaticLens { data }
383    }
384}
385
386#[derive(Default)]
387pub struct UnwrapLens<T> {
388    t: PhantomData<T>,
389}
390
391impl<T> Clone for UnwrapLens<T> {
392    fn clone(&self) -> Self {
393        *self
394    }
395}
396
397impl<T> UnwrapLens<T> {
398    pub fn new() -> Self {
399        Self { t: PhantomData }
400    }
401}
402
403impl<T> Copy for UnwrapLens<T> {}
404
405impl<T: 'static> Lens for UnwrapLens<T> {
406    type Source = Option<T>;
407    type Target = T;
408
409    fn view<'a>(&self, source: &'a Self::Source) -> Option<LensValue<'a, Self::Target>> {
410        source.as_ref().map(LensValue::Borrowed)
411    }
412}
413
414impl<T: 'static> Debug for UnwrapLens<T> {
415    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
416        f.write_str("unwrap")
417    }
418}
419
420#[derive(Default)]
421pub struct IntoLens<T, U> {
422    t: PhantomData<T>,
423    u: PhantomData<U>,
424}
425
426impl<T, U> IntoLens<T, U> {
427    pub fn new() -> Self {
428        Self { t: Default::default(), u: Default::default() }
429    }
430}
431
432impl<T, U> Clone for IntoLens<T, U> {
433    fn clone(&self) -> Self {
434        *self
435    }
436}
437
438impl<T, U> Copy for IntoLens<T, U> {}
439
440impl<T: 'static + Clone + TryInto<U>, U: 'static> Lens for IntoLens<T, U> {
441    type Source = T;
442    type Target = U;
443
444    fn view<'a>(&self, source: &'a Self::Source) -> Option<LensValue<'a, Self::Target>> {
445        source.clone().try_into().ok().map(|t| LensValue::Owned(t))
446    }
447}
448
449impl<T, U> Debug for IntoLens<T, U> {
450    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
451        f.write_str("into")
452    }
453}
454
455#[derive(Copy, Clone, Debug)]
456pub struct RatioLens<L1, L2> {
457    numerator: L1,
458    denominator: L2,
459}
460
461impl<L1, L2> RatioLens<L1, L2> {
462    pub fn new(numerator: L1, denominator: L2) -> Self {
463        Self { numerator, denominator }
464    }
465}
466
467impl<L1, L2> Lens for RatioLens<L1, L2>
468where
469    L1: 'static + Clone + Lens<Target = f32>,
470    L2: 'static + Clone + Lens<Target = f32, Source = <L1 as Lens>::Source>,
471{
472    type Source = L1::Source;
473    type Target = f32;
474
475    fn view<'a>(&self, source: &'a Self::Source) -> Option<LensValue<'a, f32>> {
476        let num = self.numerator.view(source)?.into_owned();
477        let den = self.denominator.view(source)?.into_owned();
478        Some(LensValue::Owned(num / den))
479    }
480}
481
482#[derive(Debug, Copy)]
483pub struct OrLens<L1, L2> {
484    lens1: L1,
485    lens2: L2,
486}
487
488impl<L1, L2> OrLens<L1, L2> {
489    pub fn new(lens1: L1, lens2: L2) -> Self
490    where
491        L1: Lens<Target = bool>,
492        L2: Lens<Target = bool>,
493    {
494        Self { lens1, lens2 }
495    }
496}
497
498impl<L1, L2> Lens for OrLens<L1, L2>
499where
500    L1: Lens<Source = L2::Source, Target = bool>,
501    L2: Lens<Target = bool>,
502{
503    type Source = L1::Source;
504    type Target = bool;
505
506    fn view<'a>(&self, source: &'a Self::Source) -> Option<LensValue<'a, Self::Target>> {
507        let v1 = self.lens1.view(source)?.into_owned();
508        let v2 = self.lens2.view(source)?.into_owned();
509
510        Some(LensValue::Owned(v1 | v2))
511    }
512}
513
514impl<L1: Clone, L2: Clone> Clone for OrLens<L1, L2> {
515    fn clone(&self) -> Self {
516        Self { lens1: self.lens1.clone(), lens2: self.lens2.clone() }
517    }
518}
519
520#[derive(Clone)]
521pub struct Wrapper<L>(pub L);
522
523impl<L: Copy> Copy for Wrapper<L> {}
524
525impl<L: Lens> Lens for Wrapper<L> {
526    type Source = L::Source;
527    type Target = L::Target;
528
529    fn view<'a>(&self, source: &'a Self::Source) -> Option<LensValue<'a, Self::Target>> {
530        self.0.view(source)
531    }
532}
533
534impl<L: Lens> Debug for Wrapper<L> {
535    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
536        self.0.fmt(f)
537    }
538}
539
540impl<L1: Lens<Target = bool>, L2: Lens<Target = bool>> BitOr<L2> for Wrapper<L1>
541where
542    L1: Lens<Source = L2::Source>,
543{
544    type Output = OrLens<Self, L2>;
545    fn bitor(self, rhs: L2) -> Self::Output {
546        OrLens::new(self, rhs)
547    }
548}
549
550impl<L1, L2, L3: Lens<Target = bool>> BitOr<L3> for OrLens<L1, L2>
551where
552    Self: Lens<Target = bool>,
553    Self: Lens<Source = L3::Source>,
554{
555    type Output = OrLens<Self, L3>;
556    fn bitor(self, rhs: L3) -> Self::Output {
557        OrLens::new(self, rhs)
558    }
559}
560
561impl<A: Lens, L1: Lens<Target = bool>, L2: Lens<Target = bool>> BitOr<L2> for Then<A, L1>
562where
563    A: Lens<Source = L2::Source>,
564    L1: Lens<Source = A::Target>,
565{
566    type Output = OrLens<Self, L2>;
567    fn bitor(self, rhs: L2) -> Self::Output {
568        OrLens::new(self, rhs)
569    }
570}
571
572impl<L, L2: Lens<Target = bool>> BitOr<L2> for Map<L, bool>
573where
574    L: Lens<Source = L2::Source>,
575{
576    type Output = OrLens<Self, L2>;
577    fn bitor(self, rhs: L2) -> Self::Output {
578        OrLens::new(self, rhs)
579    }
580}
581
582#[derive(Debug, Copy)]
583pub struct AndLens<L1, L2> {
584    lens1: L1,
585    lens2: L2,
586}
587
588impl<L1, L2> AndLens<L1, L2> {
589    pub fn new(lens1: L1, lens2: L2) -> Self
590    where
591        L1: Lens<Target = bool>,
592        L2: Lens<Target = bool>,
593    {
594        Self { lens1, lens2 }
595    }
596}
597
598impl<L1, L2> Lens for AndLens<L1, L2>
599where
600    L1: Lens<Source = L2::Source, Target = bool>,
601    L2: Lens<Target = bool>,
602{
603    type Source = L1::Source;
604    type Target = bool;
605
606    fn view<'a>(&self, source: &'a Self::Source) -> Option<LensValue<'a, Self::Target>> {
607        let v1 = self.lens1.view(source)?.into_owned();
608        let v2 = self.lens2.view(source)?.into_owned();
609
610        Some(LensValue::Owned(v1 | v2))
611    }
612}
613
614impl<L1: Clone, L2: Clone> Clone for AndLens<L1, L2> {
615    fn clone(&self) -> Self {
616        Self { lens1: self.lens1.clone(), lens2: self.lens2.clone() }
617    }
618}
619
620impl<L1: Lens<Target = bool>, L2: Lens<Target = bool>> BitAnd<L2> for Wrapper<L1>
621where
622    L1: Lens<Source = L2::Source>,
623{
624    type Output = AndLens<Self, L2>;
625    fn bitand(self, rhs: L2) -> Self::Output {
626        AndLens::new(self, rhs)
627    }
628}
629
630impl<L1, L2, L3: Lens<Target = bool>> BitAnd<L3> for AndLens<L1, L2>
631where
632    Self: Lens<Target = bool>,
633    Self: Lens<Source = L3::Source>,
634{
635    type Output = AndLens<Self, L3>;
636    fn bitand(self, rhs: L3) -> Self::Output {
637        AndLens::new(self, rhs)
638    }
639}
640
641impl<A: Lens, L1: Lens<Target = bool>, L2: Lens<Target = bool>> BitAnd<L2> for Then<A, L1>
642where
643    A: Lens<Source = L2::Source>,
644    L1: Lens<Source = A::Target>,
645{
646    type Output = AndLens<Self, L2>;
647    fn bitand(self, rhs: L2) -> Self::Output {
648        AndLens::new(self, rhs)
649    }
650}
651
652impl<L, L2: Lens<Target = bool>> BitAnd<L2> for Map<L, bool>
653where
654    L: Lens<Source = L2::Source>,
655{
656    type Output = AndLens<Self, L2>;
657    fn bitand(self, rhs: L2) -> Self::Output {
658        AndLens::new(self, rhs)
659    }
660}
661
662impl<T> Lens for &'static T
663where
664    T: 'static + Copy + Debug + Hash,
665{
666    type Source = ();
667    type Target = T;
668
669    fn view<'a>(&self, _source: &'a Self::Source) -> Option<LensValue<'a, Self::Target>> {
670        Some(LensValue::Borrowed(*self))
671    }
672}