1use core::fmt;
2use std::{
3 any::{Any, TypeId},
4 borrow::Cow,
5 marker::PhantomData,
6 mem,
7 sync::Arc,
8};
9
10use parking_lot::Mutex;
11use smallbox::{SmallBox, smallbox};
12use zng_clone_move::clmv;
13use zng_txt::{Txt, formatx};
14
15use crate::{
16 AnyVarModify, AnyVarValue, BoxAnyVarValue, VARS, Var, VarCapability, VarHandle, VarHandles, VarImpl, VarIsReadOnlyError, VarModify,
17 VarModifyUpdate, VarUpdateId, VarValue, WeakVarImpl,
18 animation::{Animation, AnimationController, AnimationHandle, AnimationStopFn},
19 any_contextual_var,
20};
21
22pub struct AnyVar(pub(crate) crate::var_impl::DynAnyVar);
24impl Clone for AnyVar {
25 fn clone(&self) -> Self {
26 Self(self.0.clone_dyn())
27 }
28}
29impl fmt::Debug for AnyVar {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 f.debug_tuple("AnyVar").field(&self.0).finish()
32 }
33}
34impl AnyVar {
36 pub fn with<O>(&self, visitor: impl FnOnce(&dyn AnyVarValue) -> O) -> O {
38 let mut once = Some(visitor);
39 let mut output = None;
40 self.0.with(&mut |v| {
41 output = Some(once.take().unwrap()(v));
42 });
43 output.unwrap()
44 }
45
46 pub fn get(&self) -> BoxAnyVarValue {
48 self.0.get()
49 }
50
51 pub fn get_debug(&self, alternate: bool) -> Txt {
53 let mut r = Txt::default();
54 self.0.with(&mut |v| {
55 r = if alternate { formatx!("{v:#?}") } else { formatx!("{v:?}") };
56 });
57 r
58 }
59
60 pub fn is_new(&self) -> bool {
68 self.last_update() == VARS.update_id()
69 }
70
71 pub fn get_new(&self) -> Option<BoxAnyVarValue> {
75 if self.is_new() { Some(self.get()) } else { None }
76 }
77
78 pub fn with_new<O>(&self, visitor: impl FnOnce(&dyn AnyVarValue) -> O) -> Option<O> {
82 if self.is_new() { Some(self.with(visitor)) } else { None }
83 }
84
85 pub fn try_set(&self, new_value: BoxAnyVarValue) -> Result<(), VarIsReadOnlyError> {
89 if new_value.type_id() != self.value_type() {
90 #[cfg(feature = "type_names")]
91 panic!(
92 "cannot set `{}` on variable of type `{}`",
93 new_value.type_name(),
94 self.value_type_name()
95 );
96 #[cfg(not(feature = "type_names"))]
97 panic!("cannot set variable, type mismatch");
98 }
99 self.handle_modify(self.0.set(new_value))
100 }
101
102 pub fn set(&self, new_value: BoxAnyVarValue) {
109 trace_debug_error!(self.try_set(new_value))
110 }
111
112 pub fn try_update(&self) -> Result<(), VarIsReadOnlyError> {
114 self.handle_modify(self.0.update())
115 }
116
117 pub fn update(&self) {
124 trace_debug_error!(self.try_update())
125 }
126
127 pub fn try_modify(&self, modify: impl FnOnce(&mut AnyVarModify) + Send + 'static) -> Result<(), VarIsReadOnlyError> {
131 let mut modify = Some(modify);
134 let modify = move |value: &mut AnyVarModify| {
135 #[cfg(debug_assertions)]
136 let type_id = (&*value.value as &dyn Any).type_id();
137
138 modify.take().unwrap()(value);
139
140 #[cfg(debug_assertions)]
141 if !value.update.is_empty() {
142 assert_eq!((&*value.value as &dyn Any).type_id(), type_id, "AnyVar::modify changed value type");
143 }
144 };
145
146 self.handle_modify(self.0.modify(smallbox!(modify)))
147 }
148
149 pub fn modify(&self, modify: impl FnOnce(&mut AnyVarModify) + Send + 'static) {
158 trace_debug_error!(self.try_modify(modify))
159 }
160
161 pub fn try_set_from(&self, other: &AnyVar) -> Result<(), VarIsReadOnlyError> {
166 if self.capabilities().is_read_only() {
167 return Err(VarIsReadOnlyError {});
168 }
169 let caps = other.capabilities();
170 if caps.is_const() {
171 return self.try_set(other.get());
172 }
173 let weak_other = if caps.is_contextual() {
174 let other = other.current_context();
175 if other.capabilities().is_const() {
176 return self.try_set(other.get());
177 }
178 other.downgrade()
179 } else {
180 other.downgrade()
181 };
182 self.try_modify(move |v| {
183 if let Some(other) = weak_other.upgrade() {
184 other.with(|ov| {
185 if *ov != **v {
186 let mut new_value = ov.clone_boxed();
188 assert!(v.try_swap(&mut *new_value), "set_from other var not of the same type");
189
190 v.push_tag(other.var_instance_tag());
192 }
193 v.set_modify_importance(other.modify_importance());
195 });
196 }
197 })
198 }
199
200 pub fn set_from(&self, other: &AnyVar) {
210 trace_debug_error!(self.try_set_from(other))
211 }
212
213 pub fn try_set_from_map(
217 &self,
218 other: &AnyVar,
219 map: impl FnOnce(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
220 ) -> Result<(), VarIsReadOnlyError> {
221 if self.capabilities().is_read_only() {
222 return Err(VarIsReadOnlyError {});
223 }
224 let caps = other.capabilities();
225 if caps.is_const() {
226 return self.try_set(other.with(map));
227 }
228 let weak_other = if caps.is_contextual() {
229 let other = other.current_context();
230 if other.capabilities().is_const() {
231 return self.try_set(other.with(map));
232 }
233 other.downgrade()
234 } else {
235 other.downgrade()
236 };
237 self.try_modify(move |v| {
238 if let Some(other) = weak_other.upgrade() {
239 other.with(|ov| {
240 let new_value = map(ov);
241 if v.set(new_value) {
242 v.push_tag(other.var_instance_tag());
244 }
245 v.set_modify_importance(other.modify_importance());
247 });
248 }
249 })
250 }
251
252 pub fn set_from_map(&self, other: &AnyVar, map: impl FnOnce(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) {
260 trace_debug_error!(self.try_set_from_map(other, map))
261 }
262
263 pub fn hook(&self, on_update: impl FnMut(&AnyVarHookArgs) -> bool + Send + 'static) -> VarHandle {
272 self.0.hook(smallbox!(on_update))
273 }
274
275 #[allow(clippy::manual_async_fn)] pub fn wait_match(&self, predicate: impl Fn(&dyn AnyVarValue) -> bool + Send + Sync) -> impl Future<Output = ()> + Send + Sync {
278 async move {
279 while !self.with(&predicate) {
280 let future = self.wait_update();
281 if self.with(&predicate) {
282 break;
283 }
284 future.await;
285 }
286 }
287 }
288
289 #[allow(clippy::manual_async_fn)] pub fn wait_next(&self) -> impl Future<Output = BoxAnyVarValue> + Send + Sync {
294 async {
295 self.wait_update().await;
296 self.get()
297 }
298 }
299
300 pub fn last_update(&self) -> VarUpdateId {
307 self.0.last_update()
308 }
309
310 pub fn wait_update(&self) -> impl Future<Output = VarUpdateId> + Send + Sync {
324 crate::future::WaitUpdateFut::new(self)
325 }
326
327 pub fn trace_value<S: Send + 'static>(&self, mut enter_value: impl FnMut(&AnyVarHookArgs) -> S + Send + 'static) -> VarHandle {
333 let span = self.with(|v| {
334 enter_value(&AnyVarHookArgs {
335 var_instance_tag: self.var_instance_tag(),
336 value: v,
337 update: false,
338 tags: &[],
339 })
340 });
341 let mut span = Some(span);
342 self.hook(move |v| {
343 let _ = span.take();
344 span = Some(enter_value(v));
345 true
346 })
347 }
348
349 fn handle_modify(&self, scheduled: bool) -> Result<(), VarIsReadOnlyError> {
350 match scheduled {
351 true => Ok(()),
352 false => Err(VarIsReadOnlyError {}),
353 }
354 }
355}
356impl AnyVar {
358 pub fn map_any(&self, map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static, value_type: TypeId) -> AnyVar {
367 let caps = self.capabilities();
368
369 #[cfg(debug_assertions)]
370 let map = {
371 let mut map = map;
372 move |v: &dyn AnyVarValue| {
373 let output = map(v);
374 assert_eq!(value_type, output.type_id(), "map_any value type does not match");
375 output
376 }
377 };
378
379 if caps.is_contextual() {
380 let me = self.clone();
381 let map = Arc::new(Mutex::new(map));
382 return any_contextual_var(
384 move || me.clone().map_any_tail(clmv!(map, |v| map.lock()(v)), me.capabilities()),
385 value_type,
386 );
387 }
388 self.map_any_tail(map, caps)
389 }
390 fn map_any_tail(&self, mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static, caps: VarCapability) -> AnyVar {
392 let me = self.current_context();
393
394 let mut init_value = None;
395 me.with(&mut |v: &dyn AnyVarValue| init_value = Some(map(v)));
396 let init_value = init_value.unwrap();
397
398 if caps.is_const() {
399 return crate::any_const_var(init_value);
400 }
401
402 let output = crate::any_var_derived(init_value, &me);
403 me.bind_impl(&output, map).perm();
404 output.hold(me).perm();
405
406 output.read_only()
407 }
408
409 pub fn map<O: VarValue>(&self, mut map: impl FnMut(&dyn AnyVarValue) -> O + Send + 'static) -> Var<O> {
417 let mapping = self.map_any(move |v| BoxAnyVarValue::new(map(v)), TypeId::of::<O>());
418 Var::new_any(mapping)
419 }
420
421 pub fn map_debug(&self, alternate: bool) -> Var<Txt> {
427 if alternate {
428 self.map(|v| formatx!("{v:#?}"))
429 } else {
430 self.map(|v| formatx!("{v:?}"))
431 }
432 }
433
434 pub fn filter_map_any(
444 &self,
445 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
446 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
447 value_type: TypeId,
448 ) -> AnyVar {
449 let caps = self.capabilities();
450
451 if caps.is_contextual() {
452 let me = self.clone();
453 let fns = Arc::new(Mutex::new((map, fallback_init)));
454 return any_contextual_var(
455 move || {
456 me.clone()
457 .filter_map_any_tail(clmv!(fns, |v| fns.lock().0(v)), clmv!(fns, || fns.lock().1()), me.capabilities())
458 },
459 value_type,
460 );
461 }
462
463 self.filter_map_any_tail(map, fallback_init, caps)
464 }
465 fn filter_map_any_tail(
467 &self,
468 mut map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
469 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
470 caps: VarCapability,
471 ) -> AnyVar {
472 let me = self.current_context();
473
474 let mut init_value = None;
475 me.with(&mut |v: &dyn AnyVarValue| init_value = map(v));
476 let init_value = match init_value {
477 Some(v) => v,
478 None => fallback_init(),
479 };
480
481 if caps.is_const() {
482 return crate::any_const_var(init_value);
483 }
484
485 let output = crate::any_var_derived(init_value, &me);
486 let weak_output = output.downgrade();
487
488 me.hook(move |args| {
489 match weak_output.upgrade() {
490 Some(o) => {
491 if let Some(new_value) = map(args.value) {
492 o.set(new_value);
493 }
494 true
495 }
496 None => {
497 false
499 }
500 }
501 })
502 .perm();
503 output.hold(me).perm();
504
505 output.read_only()
506 }
507
508 pub fn filter_map<O: VarValue>(
518 &self,
519 mut map: impl FnMut(&dyn AnyVarValue) -> Option<O> + Send + 'static,
520 fallback_init: impl Fn() -> O + Send + 'static,
521 ) -> Var<O> {
522 let mapping = self.filter_map_any(
523 move |v| map(v).map(BoxAnyVarValue::new),
524 move || BoxAnyVarValue::new(fallback_init()),
525 TypeId::of::<O>(),
526 );
527 Var::new_any(mapping)
528 }
529
530 pub fn map_bidi_any(
542 &self,
543 map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
544 map_back: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
545 value_type: TypeId,
546 ) -> AnyVar {
547 let caps = self.capabilities();
548
549 if caps.is_contextual() {
550 let me = self.clone();
551 let fns = Arc::new(Mutex::new((map, map_back)));
552 return any_contextual_var(
553 move || {
554 me.clone()
555 .map_bidi_tail(clmv!(fns, |v| fns.lock().0(v)), clmv!(fns, |v| fns.lock().1(v)), caps)
556 },
557 value_type,
558 );
559 }
560
561 self.map_bidi_tail(map, map_back, caps)
562 }
563 fn map_bidi_tail(
564 &self,
565 mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
566 map_back: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
567 caps: VarCapability,
568 ) -> AnyVar {
569 let me = self.current_context();
570
571 let mut init_value = None;
572 me.with(&mut |v: &dyn AnyVarValue| init_value = Some(map(v)));
573 let init_value = init_value.unwrap();
574
575 if caps.is_const() {
576 return crate::any_const_var(init_value);
577 }
578
579 let output = crate::any_var_derived(init_value, &me);
580
581 me.bind_map_bidi_any(&output, map, map_back).perm();
582 output.hold(me).perm();
583
584 output
585 }
586
587 pub fn map_bidi_modify_any(
598 &self,
599 map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
600 modify_back: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
601 value_type: TypeId,
602 ) -> AnyVar {
603 let caps = self.capabilities();
604
605 if caps.is_contextual() {
606 let me = self.clone();
607 let fns = Arc::new(Mutex::new((map, modify_back)));
608 return any_contextual_var(
609 move || {
610 me.clone()
611 .map_bidi_modify_tail(clmv!(fns, |v| fns.lock().0(v)), clmv!(fns, |v, m| fns.lock().1(v, m)), caps)
612 },
613 value_type,
614 );
615 }
616 self.map_bidi_modify_tail(map, modify_back, caps)
617 }
618 fn map_bidi_modify_tail(
619 &self,
620 mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
621 modify_back: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
622 caps: VarCapability,
623 ) -> AnyVar {
624 let me = self.current_context();
625
626 let mut init_value = None;
627 me.with(&mut |v: &dyn AnyVarValue| init_value = Some(map(v)));
628 let init_value = init_value.unwrap();
629
630 if caps.is_const() {
631 return crate::any_const_var(init_value);
632 }
633
634 let output = crate::any_var_derived(init_value, &me);
635 self.bind_map_any(&output, map).perm();
636 output.bind_modify_any(&me, modify_back).perm();
637 output.hold(me).perm();
638 output
639 }
640
641 pub fn filter_map_bidi_any(
653 &self,
654 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
655 map_back: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
656 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
657 value_type: TypeId,
658 ) -> AnyVar {
659 let caps = self.capabilities();
660
661 if caps.is_contextual() {
662 let me = self.clone();
663 let fns = Arc::new(Mutex::new((map, map_back, fallback_init)));
664 return any_contextual_var(
665 move || {
666 me.clone().filter_map_bidi_tail(
667 clmv!(fns, |v| fns.lock().0(v)),
668 clmv!(fns, |v| fns.lock().1(v)),
669 clmv!(fns, || fns.lock().2()),
670 caps,
671 )
672 },
673 value_type,
674 );
675 }
676
677 self.filter_map_bidi_tail(map, map_back, fallback_init, caps)
678 }
679 fn filter_map_bidi_tail(
680 &self,
681 mut map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
682 map_back: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
683 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
684 caps: VarCapability,
685 ) -> AnyVar {
686 let me = self.current_context();
687
688 let mut init_value = None;
689 me.with(&mut |v: &dyn AnyVarValue| init_value = map(v));
690 let init_value = init_value.unwrap_or_else(&fallback_init);
691
692 if caps.is_const() {
693 return crate::any_const_var(init_value);
694 }
695
696 let output = crate::any_var_derived(init_value, &me);
697
698 me.bind_filter_map_bidi_any(&output, map, map_back).perm();
699 output.hold(me).perm();
700
701 output
702 }
703
704 pub fn flat_map_any(&self, map: impl FnMut(&dyn AnyVarValue) -> AnyVar + Send + 'static, value_type: TypeId) -> AnyVar {
710 let caps = self.capabilities();
711
712 if caps.is_contextual() {
713 let me = self.clone();
714 let map = Arc::new(Mutex::new(map));
715 return any_contextual_var(
716 move || me.clone().flat_map_tail(clmv!(map, |v| map.lock()(v)), me.capabilities()),
717 value_type,
718 );
719 }
720
721 self.flat_map_tail(map, caps)
722 }
723 fn flat_map_tail(&self, map: impl FnMut(&dyn AnyVarValue) -> AnyVar + Send + 'static, caps: VarCapability) -> AnyVar {
724 if caps.is_const() {
725 return self.with(map);
726 }
727 let me = self.current_context();
728 let mapping = crate::var_impl::flat_map_var::FlatMapVar::new(me, smallbox!(map));
729 AnyVar(crate::DynAnyVar::FlatMap(mapping))
730 }
731
732 pub fn flat_map<O: VarValue>(&self, mut map: impl FnMut(&dyn AnyVarValue) -> Var<O> + Send + 'static) -> Var<O> {
738 let mapping = self.flat_map_any(
739 move |v| {
740 let typed = map(v);
741 typed.into()
742 },
743 TypeId::of::<O>(),
744 );
745 Var::new_any(mapping)
746 }
747}
748impl AnyVar {
750 pub fn bind(&self, other: &AnyVar) -> VarHandle {
756 self.bind_map_any(other, |v| v.clone_boxed())
757 }
758
759 pub fn set_bind(&self, other: &AnyVar) -> VarHandle {
766 other.set_from(self);
767 self.bind(other)
768 }
769
770 pub fn bind_map_any(&self, other: &AnyVar, map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) -> VarHandle {
776 let other_caps = other.capabilities();
777 if self.capabilities().is_const() || other_caps.is_always_read_only() {
778 return VarHandle::dummy();
779 }
780
781 if other_caps.is_contextual() {
782 self.bind_impl(&other.current_context(), map)
783 } else {
784 self.bind_impl(other, map)
785 }
786 }
787
788 pub fn bind_modify_any(&self, other: &AnyVar, modify: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static) -> VarHandle {
794 let self_caps = other.capabilities();
795 let other_caps = other.capabilities();
796 if self_caps.is_const() || other_caps.is_always_read_only() {
797 return VarHandle::dummy();
798 }
799
800 let mut source = Cow::Borrowed(self);
801 if self_caps.is_contextual() {
802 source = Cow::Owned(self.current_context());
803 }
804
805 if other_caps.is_contextual() {
806 source.bind_modify_impl(&other.current_context(), modify)
807 } else {
808 source.bind_modify_impl(other, modify)
809 }
810 }
811
812 pub fn set_bind_map_any(&self, other: &AnyVar, map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) -> VarHandle {
819 let map = Arc::new(Mutex::new(map));
820 other.set_from_map(self, clmv!(map, |v| map.lock()(v)));
821
822 enum MapFn<F> {
823 Hot(F),
824 Cold(Arc<Mutex<F>>),
825 Taken,
826 }
827 let mut map = MapFn::Cold(map);
828 self.bind_map_any(other, move |v| match mem::replace(&mut map, MapFn::Taken) {
829 MapFn::Hot(mut f) => {
830 let r = f(v);
831 map = MapFn::Hot(f);
832 r
833 }
834 MapFn::Cold(f) => match Arc::try_unwrap(f) {
835 Ok(f) => {
836 let mut f = f.into_inner();
837 let r = f(v);
838 map = MapFn::Hot(f);
839 r
840 }
841 Err(f) => {
842 let r = f.lock()(v);
843 map = MapFn::Cold(f);
844 r
845 }
846 },
847 MapFn::Taken => unreachable!(),
848 })
849 }
850
851 pub fn bind_map<O: VarValue>(&self, other: &Var<O>, mut map: impl FnMut(&dyn AnyVarValue) -> O + Send + 'static) -> VarHandle {
857 self.bind_map_any(other, move |v| BoxAnyVarValue::new(map(v)))
858 }
859
860 pub fn bind_modify<O: VarValue>(
866 &self,
867 other: &Var<O>,
868 mut modify: impl FnMut(&dyn AnyVarValue, &mut VarModify<O>) + Send + 'static,
869 ) -> VarHandle {
870 self.bind_modify_any(other, move |v, m| modify(v, &mut m.downcast::<O>().unwrap()))
871 }
872
873 pub fn set_bind_map<O: VarValue>(&self, other: &Var<O>, mut map: impl FnMut(&dyn AnyVarValue) -> O + Send + 'static) -> VarHandle {
880 self.set_bind_map_any(other, move |v| BoxAnyVarValue::new(map(v)))
881 }
882
883 pub fn bind_bidi(&self, other: &AnyVar) -> VarHandles {
889 self.bind_map_bidi_any(other, |v| v.clone_boxed(), |v| v.clone_boxed())
890 }
891
892 pub fn bind_map_bidi_any(
898 &self,
899 other: &AnyVar,
900 map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
901 map_back: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
902 ) -> VarHandles {
903 assert!(!self.var_eq(other), "cannot bind var to itself");
904
905 let self_cap = self.capabilities();
906 let other_cap = other.capabilities();
907 if self_cap.is_const() || other_cap.is_const() {
908 return VarHandles::dummy();
909 }
910 if self_cap.is_always_read_only() {
911 return self.bind_map_any(other, map).into();
912 }
913 if other_cap.is_always_read_only() {
914 return other.bind_map_any(self, map_back).into();
915 }
916
917 let a = if other_cap.is_contextual() {
918 self.bind_impl(&other.current_context(), map)
919 } else {
920 self.bind_impl(other, map)
921 };
922 let b = if self_cap.is_contextual() {
923 other.bind_impl(&self.current_context(), map_back)
924 } else {
925 other.bind_impl(self, map_back)
926 };
927
928 a.chain(b)
929 }
930
931 pub fn bind_modify_bidi_any(
937 &self,
938 other: &AnyVar,
939 modify: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
940 modify_back: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
941 ) -> VarHandles {
942 let self_cap = self.capabilities();
943 let other_cap = other.capabilities();
944 if self_cap.is_const() || other_cap.is_const() {
945 return VarHandles::dummy();
946 }
947 if self_cap.is_always_read_only() {
948 return self.bind_modify_any(other, modify).into();
949 }
950 if other_cap.is_always_read_only() {
951 return other.bind_modify_any(self, modify_back).into();
952 }
953
954 let mut self_ = Cow::Borrowed(self);
955 if self_cap.is_contextual() {
956 self_ = Cow::Owned(self.current_context());
957 }
958
959 let a = if other_cap.is_contextual() {
960 self_.bind_modify_impl(&other.current_context(), modify)
961 } else {
962 self_.bind_modify_impl(other, modify)
963 };
964 let b = other.bind_modify_impl(&self_, modify_back);
965
966 a.chain(b)
967 }
968
969 pub fn bind_modify_bidi<O: VarValue>(
975 &self,
976 other: &Var<O>,
977 mut modify: impl FnMut(&dyn AnyVarValue, &mut VarModify<O>) + Send + 'static,
978 mut modify_back: impl FnMut(&O, &mut AnyVarModify) + Send + 'static,
979 ) -> VarHandles {
980 self.bind_modify_bidi_any(
981 other,
982 move |v, m| modify(v, &mut m.downcast::<O>().unwrap()),
983 move |v, m| modify_back(v.downcast_ref::<O>().unwrap(), m),
984 )
985 }
986
987 pub fn bind_filter_map_any(
993 &self,
994 other: &AnyVar,
995 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
996 ) -> VarHandle {
997 if self.capabilities().is_const() || other.capabilities().is_always_read_only() {
998 return VarHandle::dummy();
999 }
1000
1001 self.bind_filter_map_impl(other, map)
1002 }
1003
1004 pub fn bind_filter_map<O: VarValue>(
1010 &self,
1011 other: &AnyVar,
1012 mut map: impl FnMut(&dyn AnyVarValue) -> Option<O> + Send + 'static,
1013 ) -> VarHandle {
1014 self.bind_filter_map_any(other, move |v| map(v).map(BoxAnyVarValue::new))
1015 }
1016
1017 pub fn bind_filter_map_bidi_any(
1024 &self,
1025 other: &AnyVar,
1026 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
1027 map_back: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
1028 ) -> VarHandles {
1029 let self_cap = self.capabilities();
1030 let other_cap = other.capabilities();
1031 if self_cap.is_const() || other_cap.is_const() {
1032 return VarHandles::dummy();
1033 }
1034 if self_cap.is_always_read_only() {
1035 return self.bind_filter_map_any(other, map).into();
1036 }
1037 if other_cap.is_always_read_only() {
1038 return other.bind_filter_map_any(self, map_back).into();
1039 }
1040
1041 let a = self.bind_filter_map_impl(other, map);
1042 let b = other.bind_filter_map_impl(self, map_back);
1043
1044 a.chain(b)
1045 }
1046
1047 fn bind_impl(&self, other: &AnyVar, mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) -> VarHandle {
1049 let weak_other = other.downgrade();
1050 self.hook(move |args| {
1051 if let Some(other) = weak_other.upgrade() {
1052 if args.contains_tag(&other.var_instance_tag()) {
1053 return true;
1055 }
1056 let self_tag = args.var_instance_tag();
1057
1058 let new_value = map(args.value());
1059 let update = args.update();
1060 other.modify(move |v| {
1061 if v.set(new_value) || update {
1062 v.push_tag(self_tag);
1064 }
1065 if update {
1066 v.update();
1068 }
1069 });
1070 true
1071 } else {
1072 false
1073 }
1074 })
1075 }
1076
1077 fn bind_modify_impl(&self, other: &AnyVar, modify: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static) -> VarHandle {
1079 let weak_other = other.downgrade();
1080 let weak_self = self.downgrade();
1081 let modify = Arc::new(Mutex::new(modify));
1082 self.hook(move |args| {
1083 if let Some(other) = weak_other.upgrade() {
1084 if args.contains_tag(&other.var_instance_tag()) {
1085 return true;
1087 }
1088
1089 let self_ = weak_self.upgrade().unwrap();
1090 let update = args.update();
1091 other.modify(clmv!(modify, |v| {
1092 let prev_update = mem::replace(&mut v.update, VarModifyUpdate::empty());
1093 self_.with(|source| {
1094 modify.lock()(source, v);
1095 });
1096
1097 if !v.update.is_empty() || update {
1098 v.push_tag(self_.var_instance_tag());
1100 }
1101 if update {
1102 v.update();
1104 }
1105 v.update |= prev_update;
1106 }));
1107 true
1108 } else {
1109 false
1110 }
1111 })
1112 }
1113
1114 fn bind_filter_map_impl(
1115 &self,
1116 other: &AnyVar,
1117 mut map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
1118 ) -> VarHandle {
1119 let weak_other = other.downgrade();
1120 self.hook(move |args| {
1121 if let Some(other) = weak_other.upgrade() {
1122 if args.contains_tag(&other.var_instance_tag()) {
1123 return true;
1125 }
1126 let self_tag = args.var_instance_tag();
1127 let update = args.update();
1128 if let Some(new_value) = map(args.value()) {
1129 other.modify(move |v| {
1130 if v.set(new_value) || update {
1131 v.push_tag(self_tag);
1133 }
1134 if update {
1135 v.update();
1137 }
1138 });
1139 } else if update {
1140 other.modify(move |v| {
1141 v.update();
1142 v.push_tag(self_tag);
1143 });
1144 }
1145
1146 true
1147 } else {
1148 false
1149 }
1150 })
1151 }
1152}
1153impl AnyVar {
1155 pub fn animate(&self, animate: impl FnMut(&Animation, &mut AnyVarModify) + Send + 'static) -> AnimationHandle {
1161 if !self.capabilities().is_always_read_only() {
1162 let target = self.current_context();
1163 if !target.capabilities().is_always_read_only() {
1164 let wk_target = target.downgrade();
1167 let animate = Arc::new(Mutex::new(animate));
1168
1169 return VARS.animate(move |args| {
1170 if let Some(target) = wk_target.upgrade() {
1173 if target.modify_importance() > VARS.current_modify().importance {
1176 args.stop();
1179 return;
1180 }
1181
1182 let r = target.try_modify(clmv!(animate, args, |value| {
1184 (animate.lock())(&args, value);
1185 }));
1186
1187 if let Err(VarIsReadOnlyError { .. }) = r {
1188 args.stop();
1190 }
1191 } else {
1192 args.stop();
1194 }
1195 });
1196 }
1197 }
1198 AnimationHandle::dummy()
1199 }
1200
1201 pub fn sequence(&self, animate: impl FnMut(AnyVar) -> AnimationHandle + Send + 'static) -> VarHandle {
1208 if !self.capabilities().is_always_read_only() {
1209 let target = self.current_context();
1210 if !target.capabilities().is_always_read_only() {
1211 let (handle_hook, handle) = VarHandle::new();
1214
1215 let wk_target = target.downgrade();
1216
1217 #[derive(Clone)]
1218 struct SequenceController(Arc<dyn Fn() + Send + Sync + 'static>);
1219 impl AnimationController for SequenceController {
1220 fn on_stop(&self, _: &Animation) {
1221 let ctrl = self.clone();
1222 VARS.with_animation_controller(ctrl, || (self.0)());
1223 }
1224 }
1225 let animate = Mutex::new(animate);
1226 let animate = Arc::new(move || {
1227 if let Some(target) = wk_target.upgrade()
1228 && target.modify_importance() <= VARS.current_modify().importance()
1229 && handle_hook.is_alive()
1230 && VARS.animations_enabled().get()
1231 {
1232 (animate.lock())(target).perm();
1233 }
1234 });
1235 VARS.with_animation_controller(SequenceController(animate.clone()), || {
1236 animate();
1237 });
1238
1239 return handle;
1240 }
1241 }
1242 VarHandle::dummy()
1243 }
1244
1245 pub fn is_animating(&self) -> bool {
1257 self.0.is_animating()
1258 }
1259
1260 pub fn modify_importance(&self) -> usize {
1270 self.0.modify_importance()
1271 }
1272
1273 pub fn hook_animation_stop(&self, handler: impl FnOnce() + Send + 'static) -> VarHandle {
1285 let mut once = Some(handler);
1286 let handler: AnimationStopFn = smallbox!(move || { once.take().unwrap()() });
1287 self.0.hook_animation_stop(handler)
1288 }
1289
1290 pub fn wait_animation(&self) -> impl Future<Output = ()> + Send + Sync {
1296 crate::future::WaitIsNotAnimatingFut::new(self)
1297 }
1298}
1299impl AnyVar {
1301 pub fn downcast<T: VarValue>(self) -> Result<Var<T>, AnyVar> {
1303 if self.value_is::<T>() { Ok(Var::new_any(self)) } else { Err(self) }
1304 }
1305
1306 pub fn downcast_or<T: VarValue, F: Into<Var<T>>>(self, fallback_var: impl FnOnce(AnyVar) -> F) -> Var<T> {
1310 match self.downcast() {
1311 Ok(tv) => tv,
1312 Err(av) => fallback_var(av).into(),
1313 }
1314 }
1315
1316 pub fn value_type(&self) -> TypeId {
1318 self.0.value_type()
1319 }
1320
1321 #[cfg(feature = "type_names")]
1325 pub fn value_type_name(&self) -> &'static str {
1326 self.0.value_type_name()
1327 }
1328
1329 pub fn value_is<T: VarValue>(&self) -> bool {
1331 self.value_type() == TypeId::of::<T>()
1332 }
1333}
1334impl AnyVar {
1336 pub fn capabilities(&self) -> VarCapability {
1338 self.0.capabilities()
1339 }
1340
1341 pub fn strong_count(&self) -> usize {
1348 self.0.strong_count()
1349 }
1350
1351 pub fn downgrade(&self) -> WeakAnyVar {
1358 WeakAnyVar(self.0.downgrade())
1359 }
1360
1361 pub fn var_eq(&self, other: &AnyVar) -> bool {
1374 self.0.var_eq(&other.0)
1375 }
1376
1377 pub fn var_instance_tag(&self) -> VarInstanceTag {
1385 self.0.var_instance_tag()
1386 }
1387
1388 pub fn read_only(&self) -> AnyVar {
1394 AnyVar(self.0.clone_dyn().into_read_only())
1395 }
1396
1397 pub fn cow(&self) -> AnyVar {
1403 let caps = self.capabilities();
1404
1405 if caps.is_contextual() {
1406 let me = self.clone();
1407 return any_contextual_var(move || me.clone().cow_tail(me.capabilities()), self.value_type());
1409 }
1410 self.cow_tail(caps)
1411 }
1412 fn cow_tail(&self, caps: VarCapability) -> AnyVar {
1414 let me = self.current_context();
1415
1416 let mut init_value = None;
1417 me.with(&mut |v: &dyn AnyVarValue| init_value = Some(v.clone_boxed()));
1418 let init_value = init_value.unwrap();
1419
1420 let output = crate::any_var_derived(init_value, &me);
1421 if caps.is_const() {
1422 return output;
1423 }
1424
1425 let read_handle = me.bind_impl(&output, |a| a.clone_boxed());
1426 output
1427 .hook(move |a| {
1428 let _hold = &read_handle;
1430 a.contains_tag(&me.var_instance_tag())
1432 })
1433 .perm();
1434
1435 output
1436 }
1437
1438 pub fn perm(&self) {
1443 VARS.perm(self.clone());
1444 }
1445
1446 pub fn hold(&self, thing: impl Any + Send) -> VarHandle {
1448 self.hold_impl(smallbox!(thing))
1449 }
1450 fn hold_impl(&self, thing: SmallBox<dyn Any + Send, smallbox::space::S2>) -> VarHandle {
1451 self.hook(move |_| {
1452 let _hold = &thing;
1453 true
1454 })
1455 }
1456
1457 pub fn hook_drop(&self, on_drop: impl FnOnce() + Send + 'static) -> VarHandle {
1461 self.hook_drop_impl(Box::new(on_drop))
1462 }
1463 fn hook_drop_impl(&self, on_drop: Box<dyn FnOnce() + Send + 'static>) -> VarHandle {
1464 let (handler_owner, handle) = VarHandle::new();
1465
1466 struct CallOnDrop(Option<Box<dyn FnOnce() + Send + 'static>>, crate::VarHandlerOwner);
1467 impl Drop for CallOnDrop {
1468 fn drop(&mut self) {
1469 if let Some(f) = self.0.take()
1470 && self.1.is_alive()
1471 {
1472 f();
1473 }
1474 }
1475 }
1476 let hold = CallOnDrop(Some(on_drop), handler_owner);
1477
1478 self.hook(move |_| hold.1.is_alive()).perm();
1479
1480 handle
1481 }
1482
1483 pub fn current_context(&self) -> AnyVar {
1490 if self.capabilities().is_contextual() {
1491 AnyVar(self.0.current_context())
1492 } else {
1493 self.clone()
1494 }
1495 }
1496}
1497
1498pub struct WeakAnyVar(pub(crate) crate::var_impl::DynWeakAnyVar);
1500impl fmt::Debug for WeakAnyVar {
1501 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1502 f.debug_tuple("WeakAnyVar").field(&self.0).finish()
1503 }
1504}
1505impl Clone for WeakAnyVar {
1506 fn clone(&self) -> Self {
1507 Self(self.0.clone_dyn())
1508 }
1509}
1510impl WeakAnyVar {
1511 pub fn strong_count(&self) -> usize {
1513 self.0.strong_count()
1514 }
1515
1516 pub fn upgrade(&self) -> Option<AnyVar> {
1518 self.0.upgrade().map(AnyVar)
1519 }
1520
1521 pub const fn new() -> Self {
1523 Self(crate::var_impl::DynWeakAnyVar::Const(crate::var_impl::const_var::WeakConstVar))
1524 }
1525
1526 pub fn var_eq(&self, other: &Self) -> bool {
1528 self.0.var_eq(&other.0)
1529 }
1530}
1531impl Default for WeakAnyVar {
1532 fn default() -> Self {
1533 Self::new()
1534 }
1535}
1536
1537pub struct AnyVarHookArgs<'a> {
1539 pub(super) var_instance_tag: VarInstanceTag,
1540 pub(super) value: &'a dyn AnyVarValue,
1541 pub(super) update: bool,
1542 pub(super) tags: &'a [BoxAnyVarValue],
1543}
1544impl<'a> AnyVarHookArgs<'a> {
1545 pub fn new(var_instance_tag: VarInstanceTag, value: &'a dyn AnyVarValue, update: bool, tags: &'a [BoxAnyVarValue]) -> Self {
1547 Self {
1548 var_instance_tag,
1549 value,
1550 update,
1551 tags,
1552 }
1553 }
1554
1555 pub fn var_instance_tag(&self) -> VarInstanceTag {
1557 self.var_instance_tag
1558 }
1559
1560 pub fn value(&self) -> &'a dyn AnyVarValue {
1562 self.value
1563 }
1564
1565 pub fn update(&self) -> bool {
1569 self.update
1570 }
1571
1572 pub fn value_type(&self) -> TypeId {
1574 self.value.type_id()
1575 }
1576
1577 pub fn tags(&self) -> &[BoxAnyVarValue] {
1579 self.tags
1580 }
1581
1582 pub fn tags_vec(&self) -> Vec<BoxAnyVarValue> {
1584 self.tags.iter().map(|t| (*t).clone_boxed()).collect()
1585 }
1586
1587 pub fn downcast_value<T: VarValue>(&self) -> Option<&T> {
1589 self.value.downcast_ref()
1590 }
1591
1592 pub fn downcast_tags<T: VarValue>(&self) -> impl Iterator<Item = &T> + '_ {
1594 self.tags.iter().filter_map(|t| (*t).downcast_ref::<T>())
1595 }
1596
1597 pub fn contains_tag<T: VarValue>(&self, tag: &T) -> bool {
1601 self.downcast_tags::<T>().any(|t| t == tag)
1602 }
1603
1604 pub fn downcast<T: VarValue>(&self) -> Option<crate::VarHookArgs<'_, T>> {
1606 if TypeId::of::<T>() == self.value_type() {
1607 Some(crate::VarHookArgs {
1608 any: self,
1609 _t: PhantomData,
1610 })
1611 } else {
1612 None
1613 }
1614 }
1615}
1616
1617#[derive(Clone, Copy, PartialEq, Eq)]
1621pub struct VarInstanceTag(pub(crate) usize);
1622impl fmt::Debug for VarInstanceTag {
1623 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1624 if *self == Self::NOT_SHARED {
1625 write!(f, "NOT_SHARED")
1626 } else {
1627 write!(f, "0x{:X}", self.0)
1628 }
1629 }
1630}
1631impl VarInstanceTag {
1632 pub const NOT_SHARED: VarInstanceTag = VarInstanceTag(0);
1636}