zng_var/
map_ref.rs

1use super::*;
2
3/// See [`Var::map_ref`].
4pub struct MapRef<I, O, S> {
5    source: S,
6    map: Arc<dyn Fn(&I) -> &O + Send + Sync>,
7}
8
9/// Weak var that can upgrade to [`MapRef<I, O, S>`] if the source is not dropped.
10pub struct WeakMapRef<I, O, S> {
11    source: S,
12    map: Arc<dyn Fn(&I) -> &O + Send + Sync>,
13}
14
15impl<I: VarValue, O: VarValue, S: Var<I>> MapRef<I, O, S> {
16    pub(super) fn new(source: S, map: Arc<dyn Fn(&I) -> &O + Send + Sync>) -> Self {
17        MapRef { source, map }
18    }
19}
20
21impl<I: VarValue, O: VarValue, S: Var<I>> crate::private::Sealed for MapRef<I, O, S> {}
22impl<I: VarValue, O: VarValue, S: WeakVar<I>> crate::private::Sealed for WeakMapRef<I, O, S> {}
23
24impl<I: VarValue, O: VarValue, S: Var<I>> Clone for MapRef<I, O, S> {
25    fn clone(&self) -> Self {
26        Self {
27            source: self.source.clone(),
28            map: self.map.clone(),
29        }
30    }
31}
32impl<I: VarValue, O: VarValue, S: WeakVar<I>> Clone for WeakMapRef<I, O, S> {
33    fn clone(&self) -> Self {
34        Self {
35            source: self.source.clone(),
36            map: self.map.clone(),
37        }
38    }
39}
40
41impl<I: VarValue, O: VarValue, S: Var<I>> AnyVar for MapRef<I, O, S> {
42    fn clone_any(&self) -> BoxedAnyVar {
43        Box::new(self.clone())
44    }
45
46    fn as_any(&self) -> &dyn Any {
47        self
48    }
49
50    fn as_unboxed_any(&self) -> &dyn Any {
51        self
52    }
53
54    fn double_boxed_any(self: Box<Self>) -> Box<dyn Any> {
55        let me: BoxedVar<O> = self;
56        Box::new(me)
57    }
58
59    fn var_type_id(&self) -> TypeId {
60        TypeId::of::<O>()
61    }
62
63    fn get_any(&self) -> Box<dyn AnyVarValue> {
64        Box::new(self.get())
65    }
66
67    fn with_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue)) {
68        self.with(|v| read(v))
69    }
70
71    fn with_new_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue)) -> bool {
72        self.with_new(|v| read(v)).is_some()
73    }
74
75    fn set_any(&self, _: Box<dyn AnyVarValue>) -> Result<(), VarIsReadOnlyError> {
76        Err(VarIsReadOnlyError {
77            capabilities: self.capabilities(),
78        })
79    }
80
81    fn last_update(&self) -> VarUpdateId {
82        self.source.last_update()
83    }
84
85    fn is_contextual(&self) -> bool {
86        self.source.is_contextual()
87    }
88
89    fn capabilities(&self) -> VarCapability {
90        self.source.capabilities().as_read_only()
91    }
92
93    fn hook_any(&self, pos_modify_action: Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync>) -> VarHandle {
94        let map = self.map.clone();
95        self.source.hook_any(Box::new(move |args| {
96            if let Some(value) = args.downcast_value() {
97                let value = map(value);
98                pos_modify_action(&AnyVarHookArgs::new(value, args.update(), args.tags()))
99            } else {
100                true
101            }
102        }))
103    }
104
105    fn hook_animation_stop(&self, handler: Box<dyn FnOnce() + Send>) -> Result<(), Box<dyn FnOnce() + Send>> {
106        self.source.hook_animation_stop(handler)
107    }
108
109    fn strong_count(&self) -> usize {
110        self.source.strong_count()
111    }
112
113    fn weak_count(&self) -> usize {
114        self.source.weak_count()
115    }
116
117    fn actual_var_any(&self) -> BoxedAnyVar {
118        Box::new(self.clone().actual_var())
119    }
120
121    fn downgrade_any(&self) -> BoxedAnyWeakVar {
122        Box::new(self.downgrade())
123    }
124
125    fn is_animating(&self) -> bool {
126        self.source.is_animating()
127    }
128
129    fn modify_importance(&self) -> usize {
130        self.source.modify_importance()
131    }
132
133    fn var_ptr(&self) -> VarPtr {
134        self.source.var_ptr()
135    }
136
137    fn get_debug(&self) -> Txt {
138        self.with(var_debug)
139    }
140
141    fn update(&self) -> Result<(), VarIsReadOnlyError> {
142        Var::modify(self, var_update)
143    }
144
145    fn map_debug(&self) -> BoxedVar<Txt> {
146        Var::map(self, var_debug).boxed()
147    }
148}
149impl<I: VarValue, O: VarValue, S: WeakVar<I>> AnyWeakVar for WeakMapRef<I, O, S> {
150    fn clone_any(&self) -> BoxedAnyWeakVar {
151        Box::new(self.clone())
152    }
153
154    fn strong_count(&self) -> usize {
155        self.source.strong_count()
156    }
157
158    fn weak_count(&self) -> usize {
159        self.source.weak_count()
160    }
161
162    fn upgrade_any(&self) -> Option<BoxedAnyVar> {
163        self.upgrade().map(|m| Box::new(m) as _)
164    }
165
166    fn as_any(&self) -> &dyn Any {
167        self
168    }
169}
170
171impl<I: VarValue, O: VarValue, S: Var<I>> IntoVar<O> for MapRef<I, O, S> {
172    type Var = Self;
173
174    fn into_var(self) -> Self::Var {
175        self
176    }
177}
178
179impl<I: VarValue, O: VarValue, S: Var<I>> Var<O> for MapRef<I, O, S> {
180    type ReadOnly = Self;
181
182    type ActualVar = MapRef<I, O, S::ActualVar>;
183
184    type Downgrade = WeakMapRef<I, O, S::Downgrade>;
185
186    type Map<MO: VarValue> = BoxedVar<MO>;
187    type MapBidi<MO: VarValue> = BoxedVar<MO>;
188
189    type FlatMap<OF: VarValue, V: Var<OF>> = BoxedVar<OF>;
190
191    type FilterMap<OF: VarValue> = BoxedVar<OF>;
192    type FilterMapBidi<OF: VarValue> = BoxedVar<OF>;
193
194    type MapRef<OM: VarValue> = types::MapRef<O, OM, Self>;
195    type MapRefBidi<OM: VarValue> = types::MapRef<O, OM, Self>;
196
197    type Easing = BoxedVar<O>;
198
199    fn with<R, F>(&self, read: F) -> R
200    where
201        F: FnOnce(&O) -> R,
202    {
203        self.source.with(|val| {
204            let val = (self.map)(val);
205            read(val)
206        })
207    }
208
209    fn modify<F>(&self, _: F) -> Result<(), VarIsReadOnlyError>
210    where
211        F: FnOnce(&mut VarModify<O>) + 'static,
212    {
213        Err(VarIsReadOnlyError {
214            capabilities: self.capabilities(),
215        })
216    }
217
218    fn actual_var(self) -> Self::ActualVar {
219        MapRef {
220            source: self.source.actual_var(),
221            map: self.map,
222        }
223    }
224
225    fn downgrade(&self) -> Self::Downgrade {
226        WeakMapRef {
227            source: self.source.downgrade(),
228            map: self.map.clone(),
229        }
230    }
231
232    fn into_value(self) -> O {
233        self.get()
234    }
235
236    fn read_only(&self) -> Self::ReadOnly {
237        self.clone()
238    }
239
240    fn map<MO, M>(&self, map: M) -> Self::Map<MO>
241    where
242        MO: VarValue,
243        M: FnMut(&O) -> MO + Send + 'static,
244    {
245        var_map_mixed(self, map)
246    }
247
248    fn map_bidi<MO, M, B>(&self, map: M, map_back: B) -> Self::MapBidi<MO>
249    where
250        MO: VarValue,
251        M: FnMut(&O) -> MO + Send + 'static,
252        B: FnMut(&MO) -> O + Send + 'static,
253    {
254        var_map_bidi_mixed(self, map, map_back)
255    }
256
257    fn flat_map<OF, V, M>(&self, map: M) -> Self::FlatMap<OF, V>
258    where
259        OF: VarValue,
260        V: Var<OF>,
261        M: FnMut(&O) -> V + Send + 'static,
262    {
263        var_flat_map_mixed(self, map)
264    }
265
266    fn filter_map<OF, M, IF>(&self, map: M, fallback: IF) -> Self::FilterMap<OF>
267    where
268        OF: VarValue,
269        M: FnMut(&O) -> Option<OF> + Send + 'static,
270        IF: Fn() -> OF + Send + Sync + 'static,
271    {
272        var_filter_map_mixed(self, map, fallback)
273    }
274
275    fn filter_map_bidi<OF, M, B, IF>(&self, map: M, map_back: B, fallback: IF) -> Self::FilterMapBidi<OF>
276    where
277        OF: VarValue,
278        M: FnMut(&O) -> Option<OF> + Send + 'static,
279        B: FnMut(&OF) -> Option<O> + Send + 'static,
280        IF: Fn() -> OF + Send + Sync + 'static,
281    {
282        var_filter_map_bidi_mixed(self, map, map_back, fallback)
283    }
284
285    fn map_ref<OM, M>(&self, map: M) -> Self::MapRef<OM>
286    where
287        OM: VarValue,
288        M: Fn(&O) -> &OM + Send + Sync + 'static,
289    {
290        var_map_ref(self, map)
291    }
292
293    fn map_ref_bidi<OM, M, B>(&self, map: M, _: B) -> Self::MapRefBidi<OM>
294    where
295        OM: VarValue,
296        M: Fn(&O) -> &OM + Send + Sync + 'static,
297        B: Fn(&mut O) -> &mut OM + Send + Sync + 'static,
298    {
299        var_map_ref(self, map)
300    }
301
302    fn easing<F>(&self, duration: Duration, easing: F) -> Self::Easing
303    where
304        O: Transitionable,
305        F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
306    {
307        var_easing_mixed(self, duration, easing)
308    }
309
310    fn easing_with<F, SE>(&self, duration: Duration, easing: F, sampler: SE) -> Self::Easing
311    where
312        O: Transitionable,
313        F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
314        SE: Fn(&animation::Transition<O>, EasingStep) -> O + Send + Sync + 'static,
315    {
316        var_easing_with_mixed(self, duration, easing, sampler)
317    }
318}
319
320impl<I: VarValue, O: VarValue, S: WeakVar<I>> WeakVar<O> for WeakMapRef<I, O, S> {
321    type Upgrade = MapRef<I, O, S::Upgrade>;
322
323    fn upgrade(&self) -> Option<Self::Upgrade> {
324        self.source.upgrade().map(|s| MapRef {
325            source: s,
326            map: self.map.clone(),
327        })
328    }
329}
330
331/// See [`Var::map_ref_bidi`].
332pub struct MapRefBidi<I, O, S> {
333    source: S,
334    map: Arc<dyn Fn(&I) -> &O + Send + Sync>,
335    map_mut: Arc<dyn Fn(&mut I) -> &mut O + Send + Sync>,
336}
337
338/// Weak var that can upgrade to [`MapRefBidi<I, O, S>`] if the source is not dropped.
339pub struct WeakMapRefBidi<I, O, S> {
340    source: S,
341    map: Arc<dyn Fn(&I) -> &O + Send + Sync>,
342    map_mut: Arc<dyn Fn(&mut I) -> &mut O + Send + Sync>,
343}
344
345impl<I: VarValue, O: VarValue, S: Var<I>> MapRefBidi<I, O, S> {
346    pub(super) fn new(source: S, map: Arc<dyn Fn(&I) -> &O + Send + Sync>, map_mut: Arc<dyn Fn(&mut I) -> &mut O + Send + Sync>) -> Self {
347        MapRefBidi { source, map, map_mut }
348    }
349}
350
351impl<I: VarValue, O: VarValue, S: Var<I>> crate::private::Sealed for MapRefBidi<I, O, S> {}
352impl<I: VarValue, O: VarValue, S: WeakVar<I>> crate::private::Sealed for WeakMapRefBidi<I, O, S> {}
353
354impl<I: VarValue, O: VarValue, S: Var<I>> Clone for MapRefBidi<I, O, S> {
355    fn clone(&self) -> Self {
356        Self {
357            source: self.source.clone(),
358            map: self.map.clone(),
359            map_mut: self.map_mut.clone(),
360        }
361    }
362}
363impl<I: VarValue, O: VarValue, S: WeakVar<I>> Clone for WeakMapRefBidi<I, O, S> {
364    fn clone(&self) -> Self {
365        Self {
366            source: self.source.clone(),
367            map: self.map.clone(),
368            map_mut: self.map_mut.clone(),
369        }
370    }
371}
372
373impl<I: VarValue, O: VarValue, S: Var<I>> AnyVar for MapRefBidi<I, O, S> {
374    fn clone_any(&self) -> BoxedAnyVar {
375        Box::new(self.clone())
376    }
377
378    fn as_any(&self) -> &dyn Any {
379        self
380    }
381
382    fn as_unboxed_any(&self) -> &dyn Any {
383        self
384    }
385
386    fn double_boxed_any(self: Box<Self>) -> Box<dyn Any> {
387        let me: BoxedVar<O> = self;
388        Box::new(me)
389    }
390
391    fn var_type_id(&self) -> TypeId {
392        TypeId::of::<O>()
393    }
394
395    fn get_any(&self) -> Box<dyn AnyVarValue> {
396        Box::new(self.get())
397    }
398
399    fn with_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue)) {
400        self.with(|v| read(v))
401    }
402
403    fn with_new_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue)) -> bool {
404        self.with_new(|v| read(v)).is_some()
405    }
406
407    fn set_any(&self, value: Box<dyn AnyVarValue>) -> Result<(), VarIsReadOnlyError> {
408        self.modify(var_set_any(value))
409    }
410
411    fn last_update(&self) -> VarUpdateId {
412        self.source.last_update()
413    }
414
415    fn is_contextual(&self) -> bool {
416        self.source.is_contextual()
417    }
418
419    fn capabilities(&self) -> VarCapability {
420        self.source.capabilities()
421    }
422
423    fn hook_any(&self, pos_modify_action: Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync>) -> VarHandle {
424        let map = self.map.clone();
425        self.source.hook_any(Box::new(move |args| {
426            if let Some(value) = args.downcast_value() {
427                let value = map(value);
428                pos_modify_action(&AnyVarHookArgs::new(value, args.update(), args.tags()))
429            } else {
430                true
431            }
432        }))
433    }
434
435    fn hook_animation_stop(&self, handler: Box<dyn FnOnce() + Send>) -> Result<(), Box<dyn FnOnce() + Send>> {
436        self.source.hook_animation_stop(handler)
437    }
438
439    fn strong_count(&self) -> usize {
440        self.source.strong_count()
441    }
442
443    fn weak_count(&self) -> usize {
444        self.source.weak_count()
445    }
446
447    fn actual_var_any(&self) -> BoxedAnyVar {
448        Box::new(self.clone().actual_var())
449    }
450
451    fn downgrade_any(&self) -> BoxedAnyWeakVar {
452        Box::new(self.downgrade())
453    }
454
455    fn is_animating(&self) -> bool {
456        self.source.is_animating()
457    }
458
459    fn modify_importance(&self) -> usize {
460        self.source.modify_importance()
461    }
462
463    fn var_ptr(&self) -> VarPtr {
464        self.source.var_ptr()
465    }
466
467    fn get_debug(&self) -> Txt {
468        self.with(var_debug)
469    }
470
471    fn update(&self) -> Result<(), VarIsReadOnlyError> {
472        Var::modify(self, var_update)
473    }
474
475    fn map_debug(&self) -> BoxedVar<Txt> {
476        Var::map(self, var_debug).boxed()
477    }
478}
479impl<I: VarValue, O: VarValue, S: WeakVar<I>> AnyWeakVar for WeakMapRefBidi<I, O, S> {
480    fn clone_any(&self) -> BoxedAnyWeakVar {
481        Box::new(self.clone())
482    }
483
484    fn strong_count(&self) -> usize {
485        self.source.strong_count()
486    }
487
488    fn weak_count(&self) -> usize {
489        self.source.weak_count()
490    }
491
492    fn upgrade_any(&self) -> Option<BoxedAnyVar> {
493        self.upgrade().map(|m| Box::new(m) as _)
494    }
495
496    fn as_any(&self) -> &dyn Any {
497        self
498    }
499}
500
501impl<I: VarValue, O: VarValue, S: Var<I>> IntoVar<O> for MapRefBidi<I, O, S> {
502    type Var = Self;
503
504    fn into_var(self) -> Self::Var {
505        self
506    }
507}
508
509impl<I: VarValue, O: VarValue, S: Var<I>> Var<O> for MapRefBidi<I, O, S> {
510    type ReadOnly = Self;
511
512    type ActualVar = MapRefBidi<I, O, S::ActualVar>;
513
514    type Downgrade = WeakMapRefBidi<I, O, S::Downgrade>;
515
516    type Map<MO: VarValue> = contextualized::ContextualizedVar<MO>;
517    type MapBidi<MO: VarValue> = contextualized::ContextualizedVar<MO>;
518
519    type FlatMap<OF: VarValue, V: Var<OF>> = contextualized::ContextualizedVar<OF>;
520
521    type FilterMap<OF: VarValue> = contextualized::ContextualizedVar<OF>;
522    type FilterMapBidi<OF: VarValue> = contextualized::ContextualizedVar<OF>;
523
524    type MapRef<OM: VarValue> = types::MapRef<O, OM, Self>;
525    type MapRefBidi<OM: VarValue> = types::MapRefBidi<O, OM, Self>;
526
527    type Easing = types::ContextualizedVar<O>;
528
529    fn with<R, F>(&self, read: F) -> R
530    where
531        F: FnOnce(&O) -> R,
532    {
533        self.source.with(|val| {
534            let val = (self.map)(val);
535            read(val)
536        })
537    }
538
539    fn modify<F>(&self, modify: F) -> Result<(), VarIsReadOnlyError>
540    where
541        F: FnOnce(&mut VarModify<O>) + Send + 'static,
542    {
543        let map = self.map.clone();
544        let map_mut = self.map_mut.clone();
545        self.source.modify(move |vm| {
546            let (notify, new_value, update, tags, custom_importance) = {
547                let mut vm = VarModify::new(map(vm.as_ref()));
548                modify(&mut vm);
549                vm.finish()
550            };
551            if let Some(i) = custom_importance {
552                vm.set_modify_importance(i);
553            }
554            if notify {
555                if update {
556                    vm.update();
557                }
558                if let Some(nv) = new_value {
559                    *map_mut(vm.to_mut()) = nv;
560                }
561                vm.push_tags(tags);
562            }
563        })
564    }
565
566    fn actual_var(self) -> Self::ActualVar {
567        MapRefBidi {
568            source: self.source.actual_var(),
569            map: self.map,
570            map_mut: self.map_mut,
571        }
572    }
573
574    fn downgrade(&self) -> Self::Downgrade {
575        WeakMapRefBidi {
576            source: self.source.downgrade(),
577            map: self.map.clone(),
578            map_mut: self.map_mut.clone(),
579        }
580    }
581
582    fn into_value(self) -> O {
583        self.get()
584    }
585
586    fn read_only(&self) -> Self::ReadOnly {
587        self.clone()
588    }
589
590    fn map<MO, M>(&self, map: M) -> Self::Map<MO>
591    where
592        MO: VarValue,
593        M: FnMut(&O) -> MO + Send + 'static,
594    {
595        var_map_ctx(self, map)
596    }
597
598    fn map_bidi<MO, M, B>(&self, map: M, map_back: B) -> Self::MapBidi<MO>
599    where
600        MO: VarValue,
601        M: FnMut(&O) -> MO + Send + 'static,
602        B: FnMut(&MO) -> O + Send + 'static,
603    {
604        var_map_bidi_ctx(self, map, map_back)
605    }
606
607    fn flat_map<OF, V, M>(&self, map: M) -> Self::FlatMap<OF, V>
608    where
609        OF: VarValue,
610        V: Var<OF>,
611        M: FnMut(&O) -> V + Send + 'static,
612    {
613        var_flat_map_ctx(self, map)
614    }
615
616    fn filter_map<OF, M, IF>(&self, map: M, fallback: IF) -> Self::FilterMap<OF>
617    where
618        OF: VarValue,
619        M: FnMut(&O) -> Option<OF> + Send + 'static,
620        IF: Fn() -> OF + Send + Sync + 'static,
621    {
622        var_filter_map_ctx(self, map, fallback)
623    }
624
625    fn filter_map_bidi<OF, M, B, IF>(&self, map: M, map_back: B, fallback: IF) -> Self::FilterMapBidi<OF>
626    where
627        OF: VarValue,
628        M: FnMut(&O) -> Option<OF> + Send + 'static,
629        B: FnMut(&OF) -> Option<O> + Send + 'static,
630        IF: Fn() -> OF + Send + Sync + 'static,
631    {
632        var_filter_map_bidi_ctx(self, map, map_back, fallback)
633    }
634
635    fn map_ref<OM, M>(&self, map: M) -> Self::MapRef<OM>
636    where
637        OM: VarValue,
638        M: Fn(&O) -> &OM + Send + Sync + 'static,
639    {
640        var_map_ref(self, map)
641    }
642
643    fn map_ref_bidi<OM, M, B>(&self, map: M, map_mut: B) -> Self::MapRefBidi<OM>
644    where
645        OM: VarValue,
646        M: Fn(&O) -> &OM + Send + Sync + 'static,
647        B: Fn(&mut O) -> &mut OM + Send + Sync + 'static,
648    {
649        var_map_ref_bidi(self, map, map_mut)
650    }
651
652    fn easing<F>(&self, duration: Duration, easing: F) -> Self::Easing
653    where
654        O: Transitionable,
655        F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
656    {
657        var_easing_ctx(self, duration, easing)
658    }
659
660    fn easing_with<F, SA>(&self, duration: Duration, easing: F, sampler: SA) -> Self::Easing
661    where
662        O: Transitionable,
663        F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
664        SA: Fn(&animation::Transition<O>, EasingStep) -> O + Send + Sync + 'static,
665    {
666        var_easing_with_ctx(self, duration, easing, sampler)
667    }
668}
669
670impl<I: VarValue, O: VarValue, S: WeakVar<I>> WeakVar<O> for WeakMapRefBidi<I, O, S> {
671    type Upgrade = MapRefBidi<I, O, S::Upgrade>;
672
673    fn upgrade(&self) -> Option<Self::Upgrade> {
674        self.source.upgrade().map(|s| MapRefBidi {
675            source: s,
676            map: self.map.clone(),
677            map_mut: self.map_mut.clone(),
678        })
679    }
680}