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