zng_var/
flat_map.rs

1use std::{
2    marker::PhantomData,
3    sync::{Arc, Weak},
4};
5
6use parking_lot::RwLock;
7
8use super::*;
9
10struct Data<T, V> {
11    _t: PhantomData<T>,
12    _source: BoxedAnyVar,
13    var: V,
14    source_handle: VarHandle,
15    last_update: VarUpdateId,
16    var_handle: VarHandle,
17    hooks: Vec<VarHook>,
18}
19
20/// See [`Var::flat_map`].
21pub struct ArcFlatMapVar<T, V>(Arc<RwLock<Data<T, V>>>);
22
23/// Weak reference to a [`ArcFlatMapVar<T, V>`].
24pub struct WeakFlatMapVar<T, V>(Weak<RwLock<Data<T, V>>>);
25
26impl<T, V> ArcFlatMapVar<T, V>
27where
28    T: VarValue,
29    V: Var<T>,
30{
31    /// New.
32    pub fn new<I: VarValue>(source: &impl Var<I>, mut map: impl FnMut(&I) -> V + Send + 'static) -> Self {
33        let flat = Arc::new(RwLock::new(Data {
34            _t: PhantomData,
35            _source: source.clone_any(),
36            var: source.with(&mut map),
37            last_update: VarUpdateId::never(),
38            source_handle: VarHandle::dummy(),
39            var_handle: VarHandle::dummy(),
40            hooks: vec![],
41        }));
42
43        {
44            let mut data = flat.write();
45            let weak_flat = Arc::downgrade(&flat);
46            let map = Mutex::new(map);
47            data.var_handle = data.var.hook_any(ArcFlatMapVar::on_var_hook(weak_flat.clone()));
48            data.source_handle = source.hook_any(Box::new(move |args| {
49                if let Some(flat) = weak_flat.upgrade() {
50                    if let Some(value) = args.downcast_value() {
51                        let mut data = flat.write();
52                        let data = &mut *data;
53                        data.var = map.lock()(value);
54                        data.var_handle = data.var.hook_any(ArcFlatMapVar::on_var_hook(weak_flat.clone()));
55                        data.last_update = VARS.update_id();
56                        data.var.with(|value| {
57                            let args = AnyVarHookArgs::new(value, args.update(), args.tags());
58                            data.hooks.retain(|h| h.call(&args));
59                        });
60                    }
61                    true
62                } else {
63                    false
64                }
65            }));
66        }
67
68        Self(flat)
69    }
70
71    fn on_var_hook(weak_flat: Weak<RwLock<Data<T, V>>>) -> Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync> {
72        Box::new(move |args| {
73            if let Some(flat) = weak_flat.upgrade() {
74                let mut data = flat.write();
75                data.last_update = VARS.update_id();
76                data.hooks.retain(|h| h.call(args));
77                true
78            } else {
79                false
80            }
81        })
82    }
83}
84
85impl<T, V> Clone for ArcFlatMapVar<T, V>
86where
87    T: VarValue,
88    V: Var<T>,
89{
90    fn clone(&self) -> Self {
91        Self(self.0.clone())
92    }
93}
94
95impl<T, V> Clone for WeakFlatMapVar<T, V>
96where
97    T: VarValue,
98    V: Var<T>,
99{
100    fn clone(&self) -> Self {
101        Self(self.0.clone())
102    }
103}
104
105impl<T, V> crate::private::Sealed for ArcFlatMapVar<T, V>
106where
107    T: VarValue,
108    V: Var<T>,
109{
110}
111
112impl<T, V> crate::private::Sealed for WeakFlatMapVar<T, V>
113where
114    T: VarValue,
115    V: Var<T>,
116{
117}
118
119impl<T, V> AnyVar for ArcFlatMapVar<T, V>
120where
121    T: VarValue,
122    V: Var<T>,
123{
124    fn clone_any(&self) -> BoxedAnyVar {
125        Box::new(self.clone())
126    }
127
128    fn as_any(&self) -> &dyn Any {
129        self
130    }
131
132    fn as_unboxed_any(&self) -> &dyn Any {
133        self
134    }
135
136    fn double_boxed_any(self: Box<Self>) -> Box<dyn Any> {
137        let me: BoxedVar<T> = self;
138        Box::new(me)
139    }
140
141    fn var_type_id(&self) -> TypeId {
142        TypeId::of::<T>()
143    }
144
145    fn get_any(&self) -> Box<dyn AnyVarValue> {
146        Box::new(self.get())
147    }
148
149    fn with_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue)) {
150        self.0.read().var.with_any(read)
151    }
152
153    fn with_new_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue)) -> bool {
154        self.0.read().var.with_new_any(read)
155    }
156
157    fn set_any(&self, value: Box<dyn AnyVarValue>) -> Result<(), VarIsReadOnlyError> {
158        self.modify(var_set_any(value))
159    }
160
161    fn last_update(&self) -> VarUpdateId {
162        self.0.read().last_update
163    }
164
165    fn is_contextual(&self) -> bool {
166        self.0.read().var.is_contextual()
167    }
168
169    fn capabilities(&self) -> VarCapability {
170        self.0.read().var.capabilities() | VarCapability::CAPS_CHANGE
171    }
172
173    fn hook_any(&self, pos_modify_action: Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync>) -> VarHandle {
174        let (handle, weak_handle) = VarHandle::new(pos_modify_action);
175        self.0.write().hooks.push(weak_handle);
176        handle
177    }
178
179    fn hook_animation_stop(&self, handler: Box<dyn FnOnce() + Send>) -> Result<(), Box<dyn FnOnce() + Send>> {
180        self.0.read().var.hook_animation_stop(handler)
181    }
182
183    fn strong_count(&self) -> usize {
184        Arc::strong_count(&self.0)
185    }
186
187    fn weak_count(&self) -> usize {
188        Arc::weak_count(&self.0)
189    }
190
191    fn actual_var_any(&self) -> BoxedAnyVar {
192        self.clone_any()
193    }
194
195    fn downgrade_any(&self) -> BoxedAnyWeakVar {
196        Box::new(self.downgrade())
197    }
198
199    fn is_animating(&self) -> bool {
200        self.0.read().var.is_animating()
201    }
202
203    fn modify_importance(&self) -> usize {
204        self.0.read().var.modify_importance()
205    }
206
207    fn var_ptr(&self) -> VarPtr {
208        VarPtr::new_arc(&self.0)
209    }
210
211    fn get_debug(&self) -> Txt {
212        self.with(var_debug)
213    }
214
215    fn update(&self) -> Result<(), VarIsReadOnlyError> {
216        Var::modify(self, var_update)
217    }
218
219    fn map_debug(&self) -> BoxedVar<Txt> {
220        Var::map(self, var_debug).boxed()
221    }
222}
223
224impl<T, V> AnyWeakVar for WeakFlatMapVar<T, V>
225where
226    T: VarValue,
227    V: Var<T>,
228{
229    fn clone_any(&self) -> BoxedAnyWeakVar {
230        Box::new(self.clone())
231    }
232
233    fn strong_count(&self) -> usize {
234        self.0.strong_count()
235    }
236
237    fn weak_count(&self) -> usize {
238        self.0.weak_count()
239    }
240
241    fn upgrade_any(&self) -> Option<BoxedAnyVar> {
242        self.0.upgrade().map(|rc| Box::new(ArcFlatMapVar(rc)) as _)
243    }
244
245    fn as_any(&self) -> &dyn Any {
246        self
247    }
248}
249
250impl<T, V> IntoVar<T> for ArcFlatMapVar<T, V>
251where
252    T: VarValue,
253    V: Var<T>,
254{
255    type Var = Self;
256
257    fn into_var(self) -> Self::Var {
258        self
259    }
260}
261
262impl<T, V> Var<T> for ArcFlatMapVar<T, V>
263where
264    T: VarValue,
265    V: Var<T>,
266{
267    type ReadOnly = types::ReadOnlyVar<T, Self>;
268
269    type ActualVar = Self;
270
271    type Downgrade = WeakFlatMapVar<T, V>;
272
273    type Map<O: VarValue> = ReadOnlyArcVar<O>;
274    type MapBidi<O: VarValue> = ArcVar<O>;
275
276    type FlatMap<O: VarValue, VF: Var<O>> = types::ArcFlatMapVar<O, VF>;
277
278    type FilterMap<O: VarValue> = ReadOnlyArcVar<O>;
279    type FilterMapBidi<O: VarValue> = ArcVar<O>;
280
281    type MapRef<O: VarValue> = types::MapRef<T, O, Self>;
282    type MapRefBidi<O: VarValue> = types::MapRefBidi<T, O, Self>;
283
284    type Easing = ReadOnlyArcVar<T>;
285
286    fn with<R, F>(&self, read: F) -> R
287    where
288        F: FnOnce(&T) -> R,
289    {
290        self.0.read_recursive().var.with(read)
291    }
292
293    fn modify<F>(&self, modify: F) -> Result<(), VarIsReadOnlyError>
294    where
295        F: FnOnce(&mut VarModify<T>) + Send + 'static,
296    {
297        self.0.read_recursive().var.modify(modify)
298    }
299
300    fn actual_var(self) -> Self {
301        self
302    }
303
304    fn downgrade(&self) -> Self::Downgrade {
305        WeakFlatMapVar(Arc::downgrade(&self.0))
306    }
307
308    fn into_value(self) -> T {
309        match Arc::try_unwrap(self.0) {
310            Ok(state) => state.into_inner().var.into_value(),
311            Err(rc) => Self(rc).get(),
312        }
313    }
314
315    fn read_only(&self) -> Self::ReadOnly {
316        types::ReadOnlyVar::new(self.clone())
317    }
318
319    fn map<O, M>(&self, map: M) -> Self::Map<O>
320    where
321        O: VarValue,
322        M: FnMut(&T) -> O + Send + 'static,
323    {
324        var_map(self, map)
325    }
326
327    fn map_bidi<O, M, B>(&self, map: M, map_back: B) -> Self::MapBidi<O>
328    where
329        O: VarValue,
330        M: FnMut(&T) -> O + Send + 'static,
331        B: FnMut(&O) -> T + Send + 'static,
332    {
333        var_map_bidi(self, map, map_back)
334    }
335
336    fn flat_map<O, VF, M>(&self, map: M) -> Self::FlatMap<O, VF>
337    where
338        O: VarValue,
339        VF: Var<O>,
340        M: FnMut(&T) -> VF + Send + 'static,
341    {
342        var_flat_map(self, map)
343    }
344
345    fn filter_map<O, M, I>(&self, map: M, fallback: I) -> Self::FilterMap<O>
346    where
347        O: VarValue,
348        M: FnMut(&T) -> Option<O> + Send + 'static,
349        I: Fn() -> O + Send + Sync + 'static,
350    {
351        var_filter_map(self, map, fallback)
352    }
353
354    fn filter_map_bidi<O, M, B, I>(&self, map: M, map_back: B, fallback: I) -> Self::FilterMapBidi<O>
355    where
356        O: VarValue,
357        M: FnMut(&T) -> Option<O> + Send + 'static,
358        B: FnMut(&O) -> Option<T> + Send + 'static,
359        I: Fn() -> O + Send + Sync + 'static,
360    {
361        var_filter_map_bidi(self, map, map_back, fallback)
362    }
363
364    fn map_ref<O, M>(&self, map: M) -> Self::MapRef<O>
365    where
366        O: VarValue,
367        M: Fn(&T) -> &O + Send + Sync + 'static,
368    {
369        var_map_ref(self, map)
370    }
371
372    fn map_ref_bidi<O, M, B>(&self, map: M, map_mut: B) -> Self::MapRefBidi<O>
373    where
374        O: VarValue,
375        M: Fn(&T) -> &O + Send + Sync + 'static,
376        B: Fn(&mut T) -> &mut O + Send + Sync + 'static,
377    {
378        var_map_ref_bidi(self, map, map_mut)
379    }
380
381    fn easing<F>(&self, duration: Duration, easing: F) -> Self::Easing
382    where
383        T: Transitionable,
384        F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
385    {
386        var_easing(self, duration, easing)
387    }
388
389    fn easing_with<F, S>(&self, duration: Duration, easing: F, sampler: S) -> Self::Easing
390    where
391        T: Transitionable,
392        F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
393        S: Fn(&animation::Transition<T>, EasingStep) -> T + Send + Sync + 'static,
394    {
395        var_easing_with(self, duration, easing, sampler)
396    }
397}
398
399impl<T, V> WeakVar<T> for WeakFlatMapVar<T, V>
400where
401    T: VarValue,
402    V: Var<T>,
403{
404    type Upgrade = ArcFlatMapVar<T, V>;
405
406    fn upgrade(&self) -> Option<Self::Upgrade> {
407        self.0.upgrade().map(|rc| ArcFlatMapVar(rc))
408    }
409}