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
20pub struct ArcFlatMapVar<T, V>(Arc<RwLock<Data<T, V>>>);
22
23pub 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 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}