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 other.current_context().downgrade()
175 } else {
176 other.downgrade()
177 };
178 self.try_modify(move |v| {
179 if let Some(other) = weak_other.upgrade() {
180 other.with(|ov| {
181 if *ov != **v {
182 let mut new_value = ov.clone_boxed();
184 assert!(v.try_swap(&mut *new_value), "set_from other var not of the same type");
185
186 v.push_tag(other.var_instance_tag());
188 }
189 v.set_modify_importance(other.modify_importance());
191 });
192 }
193 })
194 }
195
196 pub fn set_from(&self, other: &AnyVar) {
206 trace_debug_error!(self.try_set_from(other))
207 }
208
209 pub fn try_set_from_map(
213 &self,
214 other: &AnyVar,
215 map: impl FnOnce(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
216 ) -> Result<(), VarIsReadOnlyError> {
217 if self.capabilities().is_read_only() {
218 return Err(VarIsReadOnlyError {});
219 }
220 let caps = other.capabilities();
221 if caps.is_const() {
222 return self.try_set(other.with(map));
223 }
224 let weak_other = if caps.is_contextual() {
225 other.current_context().downgrade()
226 } else {
227 other.downgrade()
228 };
229 self.try_modify(move |v| {
230 if let Some(other) = weak_other.upgrade() {
231 other.with(|ov| {
232 let new_value = map(ov);
233 if v.set(new_value) {
234 v.push_tag(other.var_instance_tag());
236 }
237 v.set_modify_importance(other.modify_importance());
239 });
240 }
241 })
242 }
243
244 pub fn set_from_map(&self, other: &AnyVar, map: impl FnOnce(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) {
252 trace_debug_error!(self.try_set_from_map(other, map))
253 }
254
255 pub fn hook(&self, on_update: impl FnMut(&AnyVarHookArgs) -> bool + Send + 'static) -> VarHandle {
264 self.0.hook(smallbox!(on_update))
265 }
266
267 #[allow(clippy::manual_async_fn)] pub fn wait_match(&self, predicate: impl Fn(&dyn AnyVarValue) -> bool + Send + Sync) -> impl Future<Output = ()> + Send + Sync {
270 async move {
271 while !self.with(&predicate) {
272 let future = self.wait_update();
273 if self.with(&predicate) {
274 break;
275 }
276 future.await;
277 }
278 }
279 }
280
281 #[allow(clippy::manual_async_fn)] pub fn wait_next(&self) -> impl Future<Output = BoxAnyVarValue> + Send + Sync {
286 async {
287 self.wait_update().await;
288 self.get()
289 }
290 }
291
292 pub fn last_update(&self) -> VarUpdateId {
299 self.0.last_update()
300 }
301
302 pub fn wait_update(&self) -> impl Future<Output = VarUpdateId> + Send + Sync {
316 crate::future::WaitUpdateFut::new(self)
317 }
318
319 pub fn trace_value<S: Send + 'static>(&self, mut enter_value: impl FnMut(&AnyVarHookArgs) -> S + Send + 'static) -> VarHandle {
325 let span = self.with(|v| {
326 enter_value(&AnyVarHookArgs {
327 var_instance_tag: self.var_instance_tag(),
328 value: v,
329 update: false,
330 tags: &[],
331 })
332 });
333 let mut span = Some(span);
334 self.hook(move |v| {
335 let _ = span.take();
336 span = Some(enter_value(v));
337 true
338 })
339 }
340
341 fn handle_modify(&self, scheduled: bool) -> Result<(), VarIsReadOnlyError> {
342 match scheduled {
343 true => Ok(()),
344 false => Err(VarIsReadOnlyError {}),
345 }
346 }
347}
348impl AnyVar {
350 pub fn map_any(&self, map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static, value_type: TypeId) -> AnyVar {
359 let caps = self.capabilities();
360
361 #[cfg(debug_assertions)]
362 let map = {
363 let mut map = map;
364 move |v: &dyn AnyVarValue| {
365 let output = map(v);
366 assert_eq!(value_type, output.type_id(), "map_any value type does not match");
367 output
368 }
369 };
370
371 if caps.is_contextual() {
372 let me = self.clone();
373 let map = Arc::new(Mutex::new(map));
374 return any_contextual_var(
376 move || me.clone().map_any_tail(clmv!(map, |v| map.lock()(v)), me.capabilities()),
377 value_type,
378 );
379 }
380 self.map_any_tail(map, caps)
381 }
382 fn map_any_tail(&self, mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static, caps: VarCapability) -> AnyVar {
384 let me = self.current_context();
385
386 let mut init_value = None;
387 me.with(&mut |v: &dyn AnyVarValue| init_value = Some(map(v)));
388 let init_value = init_value.unwrap();
389
390 if caps.is_const() {
391 return crate::any_const_var(init_value);
392 }
393
394 let output = crate::any_var_derived(init_value, &me);
395 me.bind_impl(&output, map).perm();
396 output.hold(me).perm();
397
398 output.read_only()
399 }
400
401 pub fn map<O: VarValue>(&self, mut map: impl FnMut(&dyn AnyVarValue) -> O + Send + 'static) -> Var<O> {
409 let mapping = self.map_any(move |v| BoxAnyVarValue::new(map(v)), TypeId::of::<O>());
410 Var::new_any(mapping)
411 }
412
413 pub fn map_debug(&self, alternate: bool) -> Var<Txt> {
419 if alternate {
420 self.map(|v| formatx!("{v:#?}"))
421 } else {
422 self.map(|v| formatx!("{v:?}"))
423 }
424 }
425
426 pub fn filter_map_any(
436 &self,
437 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
438 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
439 value_type: TypeId,
440 ) -> AnyVar {
441 let caps = self.capabilities();
442
443 if caps.is_contextual() {
444 let me = self.clone();
445 let fns = Arc::new(Mutex::new((map, fallback_init)));
446 return any_contextual_var(
447 move || {
448 me.clone()
449 .filter_map_any_tail(clmv!(fns, |v| fns.lock().0(v)), clmv!(fns, || fns.lock().1()), me.capabilities())
450 },
451 value_type,
452 );
453 }
454
455 self.filter_map_any_tail(map, fallback_init, caps)
456 }
457 fn filter_map_any_tail(
459 &self,
460 mut map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
461 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
462 caps: VarCapability,
463 ) -> AnyVar {
464 let me = self.current_context();
465
466 let mut init_value = None;
467 me.with(&mut |v: &dyn AnyVarValue| init_value = map(v));
468 let init_value = match init_value {
469 Some(v) => v,
470 None => fallback_init(),
471 };
472
473 if caps.is_const() {
474 return crate::any_const_var(init_value);
475 }
476
477 let output = crate::any_var_derived(init_value, &me);
478 let weak_output = output.downgrade();
479
480 me.hook(move |args| {
481 match weak_output.upgrade() {
482 Some(o) => {
483 if let Some(new_value) = map(args.value) {
484 o.set(new_value);
485 }
486 true
487 }
488 None => {
489 false
491 }
492 }
493 })
494 .perm();
495 output.hold(me).perm();
496
497 output.read_only()
498 }
499
500 pub fn filter_map<O: VarValue>(
510 &self,
511 mut map: impl FnMut(&dyn AnyVarValue) -> Option<O> + Send + 'static,
512 fallback_init: impl Fn() -> O + Send + 'static,
513 ) -> Var<O> {
514 let mapping = self.filter_map_any(
515 move |v| map(v).map(BoxAnyVarValue::new),
516 move || BoxAnyVarValue::new(fallback_init()),
517 TypeId::of::<O>(),
518 );
519 Var::new_any(mapping)
520 }
521
522 pub fn map_bidi_any(
534 &self,
535 map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
536 map_back: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
537 value_type: TypeId,
538 ) -> AnyVar {
539 let caps = self.capabilities();
540
541 if caps.is_contextual() {
542 let me = self.clone();
543 let fns = Arc::new(Mutex::new((map, map_back)));
544 return any_contextual_var(
545 move || {
546 me.clone()
547 .map_bidi_tail(clmv!(fns, |v| fns.lock().0(v)), clmv!(fns, |v| fns.lock().1(v)), caps)
548 },
549 value_type,
550 );
551 }
552
553 self.map_bidi_tail(map, map_back, caps)
554 }
555 fn map_bidi_tail(
556 &self,
557 mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
558 map_back: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
559 caps: VarCapability,
560 ) -> AnyVar {
561 let me = self.current_context();
562
563 let mut init_value = None;
564 me.with(&mut |v: &dyn AnyVarValue| init_value = Some(map(v)));
565 let init_value = init_value.unwrap();
566
567 if caps.is_const() {
568 return crate::any_const_var(init_value);
569 }
570
571 let output = crate::any_var_derived(init_value, &me);
572
573 me.bind_map_bidi_any(&output, map, map_back).perm();
574 output.hold(me).perm();
575
576 output
577 }
578
579 pub fn map_bidi_modify_any(
590 &self,
591 map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
592 modify_back: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
593 value_type: TypeId,
594 ) -> AnyVar {
595 let caps = self.capabilities();
596
597 if caps.is_contextual() {
598 let me = self.clone();
599 let fns = Arc::new(Mutex::new((map, modify_back)));
600 return any_contextual_var(
601 move || {
602 me.clone()
603 .map_bidi_modify_tail(clmv!(fns, |v| fns.lock().0(v)), clmv!(fns, |v, m| fns.lock().1(v, m)), caps)
604 },
605 value_type,
606 );
607 }
608 self.map_bidi_modify_tail(map, modify_back, caps)
609 }
610 fn map_bidi_modify_tail(
611 &self,
612 mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
613 modify_back: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
614 caps: VarCapability,
615 ) -> AnyVar {
616 let me = self.current_context();
617
618 let mut init_value = None;
619 me.with(&mut |v: &dyn AnyVarValue| init_value = Some(map(v)));
620 let init_value = init_value.unwrap();
621
622 if caps.is_const() {
623 return crate::any_const_var(init_value);
624 }
625
626 let output = crate::any_var_derived(init_value, &me);
627 self.bind_map_any(&output, map).perm();
628 output.bind_modify_any(&me, modify_back).perm();
629 output.hold(me).perm();
630 output
631 }
632
633 pub fn filter_map_bidi_any(
645 &self,
646 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
647 map_back: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
648 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
649 value_type: TypeId,
650 ) -> AnyVar {
651 let caps = self.capabilities();
652
653 if caps.is_contextual() {
654 let me = self.clone();
655 let fns = Arc::new(Mutex::new((map, map_back, fallback_init)));
656 return any_contextual_var(
657 move || {
658 me.clone().filter_map_bidi_tail(
659 clmv!(fns, |v| fns.lock().0(v)),
660 clmv!(fns, |v| fns.lock().1(v)),
661 clmv!(fns, || fns.lock().2()),
662 caps,
663 )
664 },
665 value_type,
666 );
667 }
668
669 self.filter_map_bidi_tail(map, map_back, fallback_init, caps)
670 }
671 fn filter_map_bidi_tail(
672 &self,
673 mut map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
674 map_back: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
675 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
676 caps: VarCapability,
677 ) -> AnyVar {
678 let me = self.current_context();
679
680 let mut init_value = None;
681 me.with(&mut |v: &dyn AnyVarValue| init_value = map(v));
682 let init_value = init_value.unwrap_or_else(&fallback_init);
683
684 if caps.is_const() {
685 return crate::any_const_var(init_value);
686 }
687
688 let output = crate::any_var_derived(init_value, &me);
689
690 me.bind_filter_map_bidi_any(&output, map, map_back).perm();
691 output.hold(me).perm();
692
693 output
694 }
695
696 pub fn flat_map_any(&self, map: impl FnMut(&dyn AnyVarValue) -> AnyVar + Send + 'static, value_type: TypeId) -> AnyVar {
702 let caps = self.capabilities();
703
704 if caps.is_contextual() {
705 let me = self.clone();
706 let map = Arc::new(Mutex::new(map));
707 return any_contextual_var(
708 move || me.clone().flat_map_tail(clmv!(map, |v| map.lock()(v)), me.capabilities()),
709 value_type,
710 );
711 }
712
713 self.flat_map_tail(map, caps)
714 }
715 fn flat_map_tail(&self, map: impl FnMut(&dyn AnyVarValue) -> AnyVar + Send + 'static, caps: VarCapability) -> AnyVar {
716 if caps.is_const() {
717 return self.with(map);
718 }
719 let me = self.current_context();
720 let mapping = crate::var_impl::flat_map_var::FlatMapVar::new(me, smallbox!(map));
721 AnyVar(crate::DynAnyVar::FlatMap(mapping))
722 }
723
724 pub fn flat_map<O: VarValue>(&self, mut map: impl FnMut(&dyn AnyVarValue) -> Var<O> + Send + 'static) -> Var<O> {
730 let mapping = self.flat_map_any(
731 move |v| {
732 let typed = map(v);
733 typed.into()
734 },
735 TypeId::of::<O>(),
736 );
737 Var::new_any(mapping)
738 }
739}
740impl AnyVar {
742 pub fn bind(&self, other: &AnyVar) -> VarHandle {
748 self.bind_map_any(other, |v| v.clone_boxed())
749 }
750
751 pub fn set_bind(&self, other: &AnyVar) -> VarHandle {
758 other.set_from(self);
759 self.bind(other)
760 }
761
762 pub fn bind_map_any(&self, other: &AnyVar, map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) -> VarHandle {
768 let other_caps = other.capabilities();
769 if self.capabilities().is_const() || other_caps.is_always_read_only() {
770 return VarHandle::dummy();
771 }
772
773 if other_caps.is_contextual() {
774 self.bind_impl(&other.current_context(), map)
775 } else {
776 self.bind_impl(other, map)
777 }
778 }
779
780 pub fn bind_modify_any(&self, other: &AnyVar, modify: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static) -> VarHandle {
786 let self_caps = other.capabilities();
787 let other_caps = other.capabilities();
788 if self_caps.is_const() || other_caps.is_always_read_only() {
789 return VarHandle::dummy();
790 }
791
792 let mut source = Cow::Borrowed(self);
793 if self_caps.is_contextual() {
794 source = Cow::Owned(self.current_context());
795 }
796
797 if other_caps.is_contextual() {
798 source.bind_modify_impl(&other.current_context(), modify)
799 } else {
800 source.bind_modify_impl(other, modify)
801 }
802 }
803
804 pub fn set_bind_map_any(&self, other: &AnyVar, map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) -> VarHandle {
811 let map = Arc::new(Mutex::new(map));
812 other.set_from_map(self, clmv!(map, |v| map.lock()(v)));
813
814 enum MapFn<F> {
815 Hot(F),
816 Cold(Arc<Mutex<F>>),
817 Taken,
818 }
819 let mut map = MapFn::Cold(map);
820 self.bind_map_any(other, move |v| match mem::replace(&mut map, MapFn::Taken) {
821 MapFn::Hot(mut f) => {
822 let r = f(v);
823 map = MapFn::Hot(f);
824 r
825 }
826 MapFn::Cold(f) => match Arc::try_unwrap(f) {
827 Ok(f) => {
828 let mut f = f.into_inner();
829 let r = f(v);
830 map = MapFn::Hot(f);
831 r
832 }
833 Err(f) => {
834 let r = f.lock()(v);
835 map = MapFn::Cold(f);
836 r
837 }
838 },
839 MapFn::Taken => unreachable!(),
840 })
841 }
842
843 pub fn bind_map<O: VarValue>(&self, other: &Var<O>, mut map: impl FnMut(&dyn AnyVarValue) -> O + Send + 'static) -> VarHandle {
849 self.bind_map_any(other, move |v| BoxAnyVarValue::new(map(v)))
850 }
851
852 pub fn bind_modify<O: VarValue>(
858 &self,
859 other: &Var<O>,
860 mut modify: impl FnMut(&dyn AnyVarValue, &mut VarModify<O>) + Send + 'static,
861 ) -> VarHandle {
862 self.bind_modify_any(other, move |v, m| modify(v, &mut m.downcast::<O>().unwrap()))
863 }
864
865 pub fn set_bind_map<O: VarValue>(&self, other: &Var<O>, mut map: impl FnMut(&dyn AnyVarValue) -> O + Send + 'static) -> VarHandle {
872 self.set_bind_map_any(other, move |v| BoxAnyVarValue::new(map(v)))
873 }
874
875 pub fn bind_bidi(&self, other: &AnyVar) -> VarHandles {
881 self.bind_map_bidi_any(other, |v| v.clone_boxed(), |v| v.clone_boxed())
882 }
883
884 pub fn bind_map_bidi_any(
890 &self,
891 other: &AnyVar,
892 map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
893 map_back: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
894 ) -> VarHandles {
895 assert!(!self.var_eq(other), "cannot bind var to itself");
896
897 let self_cap = self.capabilities();
898 let other_cap = other.capabilities();
899 if self_cap.is_const() || other_cap.is_const() {
900 return VarHandles::dummy();
901 }
902 if self_cap.is_always_read_only() {
903 return self.bind_map_any(other, map).into();
904 }
905 if other_cap.is_always_read_only() {
906 return other.bind_map_any(self, map_back).into();
907 }
908
909 let a = if other_cap.is_contextual() {
910 self.bind_impl(&other.current_context(), map)
911 } else {
912 self.bind_impl(other, map)
913 };
914 let b = if self_cap.is_contextual() {
915 other.bind_impl(&self.current_context(), map_back)
916 } else {
917 other.bind_impl(self, map_back)
918 };
919
920 a.chain(b)
921 }
922
923 pub fn bind_modify_bidi_any(
929 &self,
930 other: &AnyVar,
931 modify: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
932 modify_back: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
933 ) -> VarHandles {
934 let self_cap = self.capabilities();
935 let other_cap = other.capabilities();
936 if self_cap.is_const() || other_cap.is_const() {
937 return VarHandles::dummy();
938 }
939 if self_cap.is_always_read_only() {
940 return self.bind_modify_any(other, modify).into();
941 }
942 if other_cap.is_always_read_only() {
943 return other.bind_modify_any(self, modify_back).into();
944 }
945
946 let mut self_ = Cow::Borrowed(self);
947 if self_cap.is_contextual() {
948 self_ = Cow::Owned(self.current_context());
949 }
950
951 let a = if other_cap.is_contextual() {
952 self_.bind_modify_impl(&other.current_context(), modify)
953 } else {
954 self_.bind_modify_impl(other, modify)
955 };
956 let b = other.bind_modify_impl(&self_, modify_back);
957
958 a.chain(b)
959 }
960
961 pub fn bind_modify_bidi<O: VarValue>(
967 &self,
968 other: &Var<O>,
969 mut modify: impl FnMut(&dyn AnyVarValue, &mut VarModify<O>) + Send + 'static,
970 mut modify_back: impl FnMut(&O, &mut AnyVarModify) + Send + 'static,
971 ) -> VarHandles {
972 self.bind_modify_bidi_any(
973 other,
974 move |v, m| modify(v, &mut m.downcast::<O>().unwrap()),
975 move |v, m| modify_back(v.downcast_ref::<O>().unwrap(), m),
976 )
977 }
978
979 pub fn bind_filter_map_any(
985 &self,
986 other: &AnyVar,
987 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
988 ) -> VarHandle {
989 if self.capabilities().is_const() || other.capabilities().is_always_read_only() {
990 return VarHandle::dummy();
991 }
992
993 self.bind_filter_map_impl(other, map)
994 }
995
996 pub fn bind_filter_map<O: VarValue>(
1002 &self,
1003 other: &AnyVar,
1004 mut map: impl FnMut(&dyn AnyVarValue) -> Option<O> + Send + 'static,
1005 ) -> VarHandle {
1006 self.bind_filter_map_any(other, move |v| map(v).map(BoxAnyVarValue::new))
1007 }
1008
1009 pub fn bind_filter_map_bidi_any(
1016 &self,
1017 other: &AnyVar,
1018 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
1019 map_back: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
1020 ) -> VarHandles {
1021 let self_cap = self.capabilities();
1022 let other_cap = other.capabilities();
1023 if self_cap.is_const() || other_cap.is_const() {
1024 return VarHandles::dummy();
1025 }
1026 if self_cap.is_always_read_only() {
1027 return self.bind_filter_map_any(other, map).into();
1028 }
1029 if other_cap.is_always_read_only() {
1030 return other.bind_filter_map_any(self, map_back).into();
1031 }
1032
1033 let a = self.bind_filter_map_impl(other, map);
1034 let b = other.bind_filter_map_impl(self, map_back);
1035
1036 a.chain(b)
1037 }
1038
1039 fn bind_impl(&self, other: &AnyVar, mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) -> VarHandle {
1041 let weak_other = other.downgrade();
1042 self.hook(move |args| {
1043 if let Some(other) = weak_other.upgrade() {
1044 if args.contains_tag(&other.var_instance_tag()) {
1045 return true;
1047 }
1048 let self_tag = args.var_instance_tag();
1049
1050 let new_value = map(args.value());
1051 let update = args.update();
1052 other.modify(move |v| {
1053 if v.set(new_value) || update {
1054 v.push_tag(self_tag);
1056 }
1057 if update {
1058 v.update();
1060 }
1061 });
1062 true
1063 } else {
1064 false
1065 }
1066 })
1067 }
1068
1069 fn bind_modify_impl(&self, other: &AnyVar, modify: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static) -> VarHandle {
1071 let weak_other = other.downgrade();
1072 let weak_self = self.downgrade();
1073 let modify = Arc::new(Mutex::new(modify));
1074 self.hook(move |args| {
1075 if let Some(other) = weak_other.upgrade() {
1076 if args.contains_tag(&other.var_instance_tag()) {
1077 return true;
1079 }
1080
1081 let self_ = weak_self.upgrade().unwrap();
1082 let update = args.update();
1083 other.modify(clmv!(modify, |v| {
1084 let prev_update = mem::replace(&mut v.update, VarModifyUpdate::empty());
1085 self_.with(|source| {
1086 modify.lock()(source, v);
1087 });
1088
1089 if !v.update.is_empty() || update {
1090 v.push_tag(self_.var_instance_tag());
1092 }
1093 if update {
1094 v.update();
1096 }
1097 v.update |= prev_update;
1098 }));
1099 true
1100 } else {
1101 false
1102 }
1103 })
1104 }
1105
1106 fn bind_filter_map_impl(
1107 &self,
1108 other: &AnyVar,
1109 mut map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
1110 ) -> VarHandle {
1111 let weak_other = other.downgrade();
1112 self.hook(move |args| {
1113 if let Some(other) = weak_other.upgrade() {
1114 if args.contains_tag(&other.var_instance_tag()) {
1115 return true;
1117 }
1118 let self_tag = args.var_instance_tag();
1119 let update = args.update();
1120 if let Some(new_value) = map(args.value()) {
1121 other.modify(move |v| {
1122 if v.set(new_value) || update {
1123 v.push_tag(self_tag);
1125 }
1126 if update {
1127 v.update();
1129 }
1130 });
1131 } else if update {
1132 other.modify(move |v| {
1133 v.update();
1134 v.push_tag(self_tag);
1135 });
1136 }
1137
1138 true
1139 } else {
1140 false
1141 }
1142 })
1143 }
1144}
1145impl AnyVar {
1147 pub fn animate(&self, animate: impl FnMut(&Animation, &mut AnyVarModify) + Send + 'static) -> AnimationHandle {
1153 if !self.capabilities().is_always_read_only() {
1154 let target = self.current_context();
1155 if !target.capabilities().is_always_read_only() {
1156 let wk_target = target.downgrade();
1159 let animate = Arc::new(Mutex::new(animate));
1160
1161 return VARS.animate(move |args| {
1162 if let Some(target) = wk_target.upgrade() {
1165 if target.modify_importance() > VARS.current_modify().importance {
1168 args.stop();
1171 return;
1172 }
1173
1174 let r = target.try_modify(clmv!(animate, args, |value| {
1176 (animate.lock())(&args, value);
1177 }));
1178
1179 if let Err(VarIsReadOnlyError { .. }) = r {
1180 args.stop();
1182 }
1183 } else {
1184 args.stop();
1186 }
1187 });
1188 }
1189 }
1190 AnimationHandle::dummy()
1191 }
1192
1193 pub fn sequence(&self, animate: impl FnMut(AnyVar) -> AnimationHandle + Send + 'static) -> VarHandle {
1200 if !self.capabilities().is_always_read_only() {
1201 let target = self.current_context();
1202 if !target.capabilities().is_always_read_only() {
1203 let (handle_hook, handle) = VarHandle::new();
1206
1207 let wk_target = target.downgrade();
1208
1209 #[derive(Clone)]
1210 struct SequenceController(Arc<dyn Fn() + Send + Sync + 'static>);
1211 impl AnimationController for SequenceController {
1212 fn on_stop(&self, _: &Animation) {
1213 let ctrl = self.clone();
1214 VARS.with_animation_controller(ctrl, || (self.0)());
1215 }
1216 }
1217 let animate = Mutex::new(animate);
1218 let animate = Arc::new(move || {
1219 if let Some(target) = wk_target.upgrade()
1220 && target.modify_importance() <= VARS.current_modify().importance()
1221 && handle_hook.is_alive()
1222 && VARS.animations_enabled().get()
1223 {
1224 (animate.lock())(target).perm();
1225 }
1226 });
1227 VARS.with_animation_controller(SequenceController(animate.clone()), || {
1228 animate();
1229 });
1230
1231 return handle;
1232 }
1233 }
1234 VarHandle::dummy()
1235 }
1236
1237 pub fn is_animating(&self) -> bool {
1249 self.0.is_animating()
1250 }
1251
1252 pub fn modify_importance(&self) -> usize {
1262 self.0.modify_importance()
1263 }
1264
1265 pub fn hook_animation_stop(&self, handler: impl FnOnce() + Send + 'static) -> VarHandle {
1277 let mut once = Some(handler);
1278 let handler: AnimationStopFn = smallbox!(move || { once.take().unwrap()() });
1279 self.0.hook_animation_stop(handler)
1280 }
1281
1282 pub fn wait_animation(&self) -> impl Future<Output = ()> + Send + Sync {
1288 crate::future::WaitIsNotAnimatingFut::new(self)
1289 }
1290}
1291impl AnyVar {
1293 pub fn downcast<T: VarValue>(self) -> Result<Var<T>, AnyVar> {
1295 if self.value_is::<T>() { Ok(Var::new_any(self)) } else { Err(self) }
1296 }
1297
1298 pub fn downcast_or<T: VarValue, F: Into<Var<T>>>(self, fallback_var: impl FnOnce(AnyVar) -> F) -> Var<T> {
1302 match self.downcast() {
1303 Ok(tv) => tv,
1304 Err(av) => fallback_var(av).into(),
1305 }
1306 }
1307
1308 pub fn value_type(&self) -> TypeId {
1310 self.0.value_type()
1311 }
1312
1313 #[cfg(feature = "type_names")]
1317 pub fn value_type_name(&self) -> &'static str {
1318 self.0.value_type_name()
1319 }
1320
1321 pub fn value_is<T: VarValue>(&self) -> bool {
1323 self.value_type() == TypeId::of::<T>()
1324 }
1325}
1326impl AnyVar {
1328 pub fn capabilities(&self) -> VarCapability {
1330 self.0.capabilities()
1331 }
1332
1333 pub fn strong_count(&self) -> usize {
1340 self.0.strong_count()
1341 }
1342
1343 pub fn downgrade(&self) -> WeakAnyVar {
1350 WeakAnyVar(self.0.downgrade())
1351 }
1352
1353 pub fn var_eq(&self, other: &AnyVar) -> bool {
1359 self.0.var_eq(&other.0)
1360 }
1361
1362 pub fn var_instance_tag(&self) -> VarInstanceTag {
1370 self.0.var_instance_tag()
1371 }
1372
1373 pub fn read_only(&self) -> AnyVar {
1379 AnyVar(self.0.clone_dyn().into_read_only())
1380 }
1381
1382 pub fn cow(&self) -> AnyVar {
1388 let caps = self.capabilities();
1389
1390 if caps.is_contextual() {
1391 let me = self.clone();
1392 return any_contextual_var(move || me.clone().cow_tail(me.capabilities()), self.value_type());
1394 }
1395 self.cow_tail(caps)
1396 }
1397 fn cow_tail(&self, caps: VarCapability) -> AnyVar {
1399 let me = self.current_context();
1400
1401 let mut init_value = None;
1402 me.with(&mut |v: &dyn AnyVarValue| init_value = Some(v.clone_boxed()));
1403 let init_value = init_value.unwrap();
1404
1405 let output = crate::any_var_derived(init_value, &me);
1406 if caps.is_const() {
1407 return output;
1408 }
1409
1410 let read_handle = me.bind_impl(&output, |a| a.clone_boxed());
1411 output
1412 .hook(move |a| {
1413 let _hold = &read_handle;
1415 a.contains_tag(&me.var_instance_tag())
1417 })
1418 .perm();
1419
1420 output
1421 }
1422
1423 pub fn perm(&self) {
1428 VARS.perm(self.clone());
1429 }
1430
1431 pub fn hold(&self, thing: impl Any + Send) -> VarHandle {
1433 self.hold_impl(smallbox!(thing))
1434 }
1435 fn hold_impl(&self, thing: SmallBox<dyn Any + Send, smallbox::space::S2>) -> VarHandle {
1436 self.hook(move |_| {
1437 let _hold = &thing;
1438 true
1439 })
1440 }
1441
1442 pub fn hook_drop(&self, on_drop: impl FnOnce() + Send + 'static) -> VarHandle {
1446 self.hook_drop_impl(Box::new(on_drop))
1447 }
1448 fn hook_drop_impl(&self, on_drop: Box<dyn FnOnce() + Send + 'static>) -> VarHandle {
1449 let (handler_owner, handle) = VarHandle::new();
1450
1451 struct CallOnDrop(Option<Box<dyn FnOnce() + Send + 'static>>, crate::VarHandlerOwner);
1452 impl Drop for CallOnDrop {
1453 fn drop(&mut self) {
1454 if let Some(f) = self.0.take()
1455 && self.1.is_alive()
1456 {
1457 f();
1458 }
1459 }
1460 }
1461 let hold = CallOnDrop(Some(on_drop), handler_owner);
1462
1463 self.hook(move |_| hold.1.is_alive()).perm();
1464
1465 handle
1466 }
1467
1468 pub fn current_context(&self) -> AnyVar {
1475 if self.capabilities().is_contextual() {
1476 AnyVar(self.0.current_context())
1477 } else {
1478 self.clone()
1479 }
1480 }
1481}
1482
1483pub struct WeakAnyVar(pub(crate) crate::var_impl::DynWeakAnyVar);
1485impl fmt::Debug for WeakAnyVar {
1486 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1487 f.debug_tuple("WeakAnyVar").field(&self.0).finish()
1488 }
1489}
1490impl Clone for WeakAnyVar {
1491 fn clone(&self) -> Self {
1492 Self(self.0.clone_dyn())
1493 }
1494}
1495impl WeakAnyVar {
1496 pub fn strong_count(&self) -> usize {
1498 self.0.strong_count()
1499 }
1500
1501 pub fn upgrade(&self) -> Option<AnyVar> {
1503 self.0.upgrade().map(AnyVar)
1504 }
1505
1506 pub const fn new() -> Self {
1508 Self(crate::var_impl::DynWeakAnyVar::Const(crate::var_impl::const_var::WeakConstVar))
1509 }
1510
1511 pub fn var_eq(&self, other: &Self) -> bool {
1513 self.0.var_eq(&other.0)
1514 }
1515}
1516impl Default for WeakAnyVar {
1517 fn default() -> Self {
1518 Self::new()
1519 }
1520}
1521
1522pub struct AnyVarHookArgs<'a> {
1524 pub(super) var_instance_tag: VarInstanceTag,
1525 pub(super) value: &'a dyn AnyVarValue,
1526 pub(super) update: bool,
1527 pub(super) tags: &'a [BoxAnyVarValue],
1528}
1529impl<'a> AnyVarHookArgs<'a> {
1530 pub fn new(var_instance_tag: VarInstanceTag, value: &'a dyn AnyVarValue, update: bool, tags: &'a [BoxAnyVarValue]) -> Self {
1532 Self {
1533 var_instance_tag,
1534 value,
1535 update,
1536 tags,
1537 }
1538 }
1539
1540 pub fn var_instance_tag(&self) -> VarInstanceTag {
1542 self.var_instance_tag
1543 }
1544
1545 pub fn value(&self) -> &'a dyn AnyVarValue {
1547 self.value
1548 }
1549
1550 pub fn update(&self) -> bool {
1554 self.update
1555 }
1556
1557 pub fn value_type(&self) -> TypeId {
1559 self.value.type_id()
1560 }
1561
1562 pub fn tags(&self) -> &[BoxAnyVarValue] {
1564 self.tags
1565 }
1566
1567 pub fn tags_vec(&self) -> Vec<BoxAnyVarValue> {
1569 self.tags.iter().map(|t| (*t).clone_boxed()).collect()
1570 }
1571
1572 pub fn downcast_value<T: VarValue>(&self) -> Option<&T> {
1574 self.value.downcast_ref()
1575 }
1576
1577 pub fn downcast_tags<T: VarValue>(&self) -> impl Iterator<Item = &T> + '_ {
1579 self.tags.iter().filter_map(|t| (*t).downcast_ref::<T>())
1580 }
1581
1582 pub fn contains_tag<T: VarValue>(&self, tag: &T) -> bool {
1586 self.downcast_tags::<T>().any(|t| t == tag)
1587 }
1588
1589 pub fn downcast<T: VarValue>(&self) -> Option<crate::VarHookArgs<'_, T>> {
1591 if TypeId::of::<T>() == self.value_type() {
1592 Some(crate::VarHookArgs {
1593 any: self,
1594 _t: PhantomData,
1595 })
1596 } else {
1597 None
1598 }
1599 }
1600}
1601
1602#[derive(Clone, Copy, PartialEq, Eq)]
1606pub struct VarInstanceTag(pub(crate) usize);
1607impl fmt::Debug for VarInstanceTag {
1608 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1609 if *self == Self::NOT_SHARED {
1610 write!(f, "NOT_SHARED")
1611 } else {
1612 write!(f, "0x{:X}", self.0)
1613 }
1614 }
1615}
1616impl VarInstanceTag {
1617 pub const NOT_SHARED: VarInstanceTag = VarInstanceTag(0);
1621}