1use std::{
2 any::{Any, TypeId},
3 fmt,
4 marker::PhantomData,
5 mem, ops,
6 sync::{Arc, atomic::AtomicBool},
7};
8
9use crate::{
10 AnyVarHookArgs, AnyVarValue, BoxAnyVarValue, VarInstanceTag, VarUpdateId, VarValue,
11 animation::{AnimationStopFn, ModifyInfo},
12 read_only_var::ReadOnlyImpl,
13};
14use bitflags::bitflags;
15use smallbox::{SmallBox, smallbox};
16
17pub(crate) mod shared_var;
18pub use shared_var::{any_var, any_var_derived, var, var_derived, var_getter, var_state};
19
20pub(crate) mod const_var;
21pub use const_var::IntoVar;
22pub(crate) mod flat_map_var;
23pub(crate) mod read_only_var;
24
25pub(crate) mod contextual_var;
26pub use contextual_var::{ContextInitHandle, WeakContextInitHandle, any_contextual_var, contextual_var};
27
28pub(crate) mod context_var;
29pub use context_var::{__context_var_local, ContextVar, context_var_init};
30
31pub(crate) mod merge_var;
32pub use merge_var::{
33 __merge_var, AnyMergeVarBuilder, MergeInput, MergeVarBuilder, MergeVarInputs, merge_var, merge_var_input, merge_var_output,
34 merge_var_with,
35};
36
37pub(crate) mod response_var;
38pub use response_var::{ResponderVar, Response, ResponseVar, response_done_var, response_var};
39
40pub(crate) mod when_var;
41pub use when_var::{__when_var, AnyWhenVarBuilder, WhenVarBuilder};
42
43pub(crate) mod expr_var;
44pub use expr_var::{__expr_var, expr_var_as, expr_var_into, expr_var_map};
45
46pub(crate) enum DynAnyVar {
47 Const(const_var::ConstVar),
48 When(when_var::WhenVar),
49
50 Shared(shared_var::SharedVar),
51 Context(context_var::ContextVarImpl),
52 FlatMap(flat_map_var::FlatMapVar),
53 Contextual(contextual_var::ContextualVar),
54
55 ReadOnlyShared(ReadOnlyImpl<shared_var::SharedVar>),
56 ReadOnlyFlatMap(ReadOnlyImpl<flat_map_var::FlatMapVar>),
57 ReadOnlyContext(ReadOnlyImpl<context_var::ContextVarImpl>),
58 ReadOnlyContextual(ReadOnlyImpl<contextual_var::ContextualVar>),
59}
60macro_rules! dispatch {
61 ($self:ident, $var:ident => $($tt:tt)+) => {
62 match $self {
63 DynAnyVar::Const($var) => $($tt)+,
64 DynAnyVar::FlatMap($var) => $($tt)+,
65 DynAnyVar::When($var) => $($tt)+,
66
67 DynAnyVar::Shared($var) => $($tt)+,
68 DynAnyVar::Context($var) => $($tt)+,
69 DynAnyVar::Contextual($var) => $($tt)+,
70
71 DynAnyVar::ReadOnlyShared($var) => $($tt)+,
72 DynAnyVar::ReadOnlyFlatMap($var) => $($tt)+,
73 DynAnyVar::ReadOnlyContext($var) => $($tt)+,
74 DynAnyVar::ReadOnlyContextual($var) => $($tt)+,
75 }
76 };
77}
78impl fmt::Debug for DynAnyVar {
79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80 dispatch!(self, v => fmt::Debug::fmt(v, f))
81 }
82}
83
84pub(crate) enum DynWeakAnyVar {
85 Const(const_var::WeakConstVar),
86 When(when_var::WeakWhenVar),
87
88 Shared(shared_var::WeakSharedVar),
89 Context(context_var::ContextVarImpl),
90 FlatMap(flat_map_var::WeakFlatMapVar),
91 Contextual(contextual_var::WeakContextualVar),
92
93 ReadOnlyShared(ReadOnlyImpl<shared_var::WeakSharedVar>),
94 ReadOnlyContext(ReadOnlyImpl<context_var::ContextVarImpl>),
95 ReadOnlyContextual(ReadOnlyImpl<contextual_var::WeakContextualVar>),
96 ReadOnlyFlatMap(ReadOnlyImpl<flat_map_var::WeakFlatMapVar>),
97}
98macro_rules! dispatch_weak {
99 ($self:ident, $var:ident => $($tt:tt)+) => {
100 match $self {
101 DynWeakAnyVar::Const($var) => $($tt)+,
102 DynWeakAnyVar::Shared($var) => $($tt)+,
103 DynWeakAnyVar::Context($var) => $($tt)+,
104 DynWeakAnyVar::Contextual($var) => $($tt)+,
105 DynWeakAnyVar::FlatMap($var) => $($tt)+,
106 DynWeakAnyVar::When($var) => $($tt)+,
107 DynWeakAnyVar::ReadOnlyShared($var) => $($tt)+,
108 DynWeakAnyVar::ReadOnlyContext($var) => $($tt)+,
109 DynWeakAnyVar::ReadOnlyContextual($var) => $($tt)+,
110 DynWeakAnyVar::ReadOnlyFlatMap($var) => $($tt)+,
111
112 }
113 };
114}
115impl fmt::Debug for DynWeakAnyVar {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 dispatch_weak!(self, v => fmt::Debug::fmt(v, f))
118 }
119}
120
121macro_rules! declare {
122 ($(
123 $(#[$meta:meta])*
124 fn $method:ident(&self $(, $arg:ident : $Input:ty)*) $(-> $Output:ty)?;
125 )+) => {
126 pub(crate) trait VarImpl: fmt::Debug + Any + Send + Sync {
127 $(
128 $(#[$meta])*
129 fn $method(&self $(, $arg: $Input)*) $(-> $Output)?;
130 )+
131 }
132
133 impl VarImpl for DynAnyVar {
134 $(
135 $(#[$meta])*
136 fn $method(&self $(, $arg: $Input)*) $(-> $Output)? {
137 dispatch!(self, v => VarImpl::$method(v$(, $arg)*))
138 }
139 )+
140 }
141 };
142}
143declare! {
144 fn clone_dyn(&self) -> DynAnyVar;
145 fn value_type(&self) -> TypeId;
146 #[cfg(feature = "type_names")]
147 fn value_type_name(&self) -> &'static str;
148 fn strong_count(&self) -> usize;
149 fn var_eq(&self, other: &DynAnyVar) -> bool;
150 fn var_instance_tag(&self) -> VarInstanceTag;
151 fn downgrade(&self) -> DynWeakAnyVar;
152 fn capabilities(&self) -> VarCapability;
153 fn with(&self, visitor: &mut dyn FnMut(&dyn AnyVarValue));
154 fn get(&self) -> BoxAnyVarValue;
155 fn set(&self, new_value: BoxAnyVarValue) -> bool;
156 fn update(&self) -> bool;
157 fn modify(&self, modify: SmallBox<dyn FnMut(&mut AnyVarModify) + Send + 'static, smallbox::space::S4>) -> bool;
158 fn hook(&self, on_new: SmallBox<dyn FnMut(&AnyVarHookArgs) -> bool + Send + 'static, smallbox::space::S4>) -> VarHandle;
159 fn last_update(&self) -> VarUpdateId;
160 fn modify_importance(&self) -> usize;
161 fn is_animating(&self) -> bool;
162 fn hook_animation_stop(&self, handler: AnimationStopFn) -> VarHandle;
163 fn current_context(&self) -> DynAnyVar;
164 fn modify_info(&self) -> ModifyInfo;
165}
166
167macro_rules! declare_weak {
168 ($(
169 fn $method:ident(&self $(, $arg:ident : $Input:ty)*) $(-> $Output:ty)?;
170 )+) => {
171 pub(crate) trait WeakVarImpl: fmt::Debug + Any + Send + Sync {
172 $(
173 fn $method(&self $(, $arg: $Input)*) $(-> $Output)?;
174 )+
175 }
176
177 impl WeakVarImpl for DynWeakAnyVar {
178 $(
179 fn $method(&self $(, $arg: $Input)*) $(-> $Output)? {
180 dispatch_weak!(self, v => WeakVarImpl::$method(v$(, $arg)*))
181 }
182 )+
183 }
184 };
185}
186declare_weak! {
187 fn clone_dyn(&self) -> DynWeakAnyVar;
188 fn strong_count(&self) -> usize;
189 fn upgrade(&self) -> Option<DynAnyVar>;
190 fn var_eq(&self, other: &DynWeakAnyVar) -> bool;
191}
192
193#[derive(Debug, Clone, Copy)]
197#[non_exhaustive]
198pub struct VarIsReadOnlyError {}
199impl fmt::Display for VarIsReadOnlyError {
200 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
201 write!(f, "cannot modify read-only variable")
202 }
203}
204impl std::error::Error for VarIsReadOnlyError {}
205
206bitflags! {
207 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
214 pub struct VarCapability: u8 {
215 const NEW = 0b0000_0010;
222
223 const MODIFY = 0b0000_0011;
232
233 const CONTEXT = 0b1000_0000;
235
236 const MODIFY_CHANGES = 0b0100_0000;
238 const CONTEXT_CHANGES = 0b0010_0000;
240
241 const SHARE = 0b0001_0000;
244 }
245}
246impl VarCapability {
247 pub fn is_const(self) -> bool {
249 self.is_empty()
250 }
251
252 pub fn is_always_read_only(&self) -> bool {
254 !self.contains(Self::MODIFY) && !self.contains(Self::MODIFY_CHANGES)
255 }
256
257 pub fn is_read_only(self) -> bool {
259 !self.can_modify()
260 }
261
262 pub fn can_modify(self) -> bool {
264 self.contains(Self::MODIFY)
265 }
266
267 pub fn is_contextual(self) -> bool {
269 self.contains(Self::CONTEXT)
270 }
271
272 pub fn is_always_contextual(self) -> bool {
274 self.contains(Self::CONTEXT) && !self.contains(Self::CONTEXT_CHANGES)
275 }
276
277 pub fn is_share(&self) -> bool {
279 self.contains(Self::SHARE)
280 }
281
282 pub fn is_local(&self) -> bool {
286 !self.is_share()
287 }
288}
289impl VarCapability {
290 pub(crate) fn as_always_read_only(self) -> Self {
291 let mut out = self;
292
293 out.remove(Self::MODIFY & !Self::NEW);
295 out.remove(Self::MODIFY_CHANGES);
297
298 out
299 }
300}
301
302bitflags! {
303 #[derive(Clone, Copy)]
304 pub(crate) struct VarModifyUpdate: u8 {
305 const UPDATE = 0b001;
307 const REQUESTED = 0b011;
309 const TOUCHED = 0b101;
311 }
312}
313
314pub struct AnyVarModify<'a> {
318 pub(crate) value: &'a mut BoxAnyVarValue,
319 pub(crate) update: VarModifyUpdate,
320 pub(crate) tags: Vec<BoxAnyVarValue>,
321 pub(crate) custom_importance: Option<usize>,
322}
323impl<'a> AnyVarModify<'a> {
324 pub fn set(&mut self, mut new_value: BoxAnyVarValue) -> bool {
328 if **self.value != *new_value {
329 if !self.value.try_swap(&mut *new_value) {
330 #[cfg(feature = "type_names")]
331 panic!(
332 "cannot AnyVarModify::set `{}` on variable of type `{}`",
333 new_value.type_name(),
334 self.value.type_name()
335 );
336 #[cfg(not(feature = "type_names"))]
337 panic!("cannot modify set, type mismatch");
338 }
339 self.update |= VarModifyUpdate::TOUCHED;
340 true
341 } else {
342 false
343 }
344 }
345
346 pub fn update(&mut self) {
348 self.update |= VarModifyUpdate::REQUESTED;
349 }
350
351 pub fn tags(&self) -> &[BoxAnyVarValue] {
356 &self.tags
357 }
358
359 pub fn push_tag(&mut self, tag: impl AnyVarValue) {
361 self.tags.push(BoxAnyVarValue::new(tag));
362 }
363
364 pub fn set_modify_importance(&mut self, importance: usize) {
372 self.custom_importance = Some(importance);
373 }
374
375 pub fn downcast<'s, T: VarValue>(&'s mut self) -> Option<VarModify<'s, 'a, T>> {
377 if self.value.is::<T>() {
378 Some(VarModify {
379 inner: self,
380 _t: PhantomData,
381 })
382 } else {
383 None
384 }
385 }
386
387 pub fn value(&self) -> &dyn AnyVarValue {
391 &**self
392 }
393
394 pub fn value_mut(&mut self) -> &mut dyn AnyVarValue {
400 &mut **self
401 }
402
403 pub fn check_update(&mut self, f: impl FnOnce(&mut Self)) -> bool {
411 let u = mem::replace(&mut self.update, VarModifyUpdate::empty());
412 f(self);
413 let has_update = !self.update.is_empty();
414 self.update |= u;
415 has_update
416 }
417}
418impl<'a> ops::Deref for AnyVarModify<'a> {
419 type Target = dyn AnyVarValue;
420
421 fn deref(&self) -> &Self::Target {
422 &**self.value
423 }
424}
425impl<'a> ops::DerefMut for AnyVarModify<'a> {
426 fn deref_mut(&mut self) -> &mut Self::Target {
427 self.update |= VarModifyUpdate::TOUCHED;
428 self.value.deref_mut()
429 }
430}
431
432pub struct VarModify<'s, 'a, T: VarValue> {
436 inner: &'s mut AnyVarModify<'a>,
437 _t: PhantomData<fn() -> &'a T>,
438}
439impl<'s, 'a, T: VarValue> VarModify<'s, 'a, T> {
440 pub fn set(&mut self, new_value: impl Into<T>) -> bool {
444 let new_value = new_value.into();
445 if **self != new_value {
446 **self = new_value;
447 true
448 } else {
449 false
450 }
451 }
452
453 pub fn update(&mut self) {
455 self.inner.update();
456 }
457
458 pub fn tags(&self) -> &[BoxAnyVarValue] {
463 self.inner.tags()
464 }
465
466 pub fn push_tag(&mut self, tag: impl AnyVarValue) {
468 self.inner.push_tag(tag);
469 }
470
471 pub fn set_modify_importance(&mut self, importance: usize) {
479 self.inner.set_modify_importance(importance);
480 }
481
482 pub fn as_any(&mut self) -> &mut AnyVarModify<'a> {
484 self.inner
485 }
486
487 pub fn value(&self) -> &T {
491 self
492 }
493
494 pub fn value_mut(&mut self) -> &mut T {
500 self
501 }
502
503 pub fn check_update(&mut self, f: impl FnOnce(&mut Self)) -> bool {
511 let u = mem::replace(&mut self.inner.update, VarModifyUpdate::empty());
512 f(self);
513 let has_update = !self.inner.update.is_empty();
514 self.inner.update |= u;
515 has_update
516 }
517}
518impl<'s, 'a, T: VarValue> ops::Deref for VarModify<'s, 'a, T> {
519 type Target = T;
520
521 fn deref(&self) -> &Self::Target {
522 self.inner.downcast_ref().unwrap()
523 }
524}
525impl<'s, 'a, T: VarValue> ops::DerefMut for VarModify<'s, 'a, T> {
526 fn deref_mut(&mut self) -> &mut Self::Target {
527 self.inner.downcast_mut().unwrap()
528 }
529}
530
531#[derive(Clone, Default)]
539#[must_use = "var handle stops the behavior it represents on drop"]
540pub struct VarHandle(Option<Arc<AtomicBool>>);
541impl PartialEq for VarHandle {
542 fn eq(&self, other: &Self) -> bool {
543 if let Some(a) = &self.0
544 && let Some(b) = &other.0
545 {
546 Arc::ptr_eq(a, b)
547 } else {
548 false
549 }
550 }
551}
552impl fmt::Debug for VarHandle {
553 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
554 if self.is_dummy() {
555 write!(f, "VarHandle(<dummy>)")
556 } else {
557 f.debug_tuple("VarHandle").finish_non_exhaustive()
558 }
559 }
560}
561impl VarHandle {
562 pub const fn dummy() -> Self {
564 VarHandle(None)
565 }
566
567 pub(crate) fn new() -> (VarHandlerOwner, Self) {
568 let h = Arc::new(AtomicBool::new(false));
569 (VarHandlerOwner(h.clone()), Self(Some(h)))
570 }
571
572 pub fn is_dummy(&self) -> bool {
576 self.0.is_none()
577 }
578
579 pub fn perm(self) {
583 if let Some(c) = &self.0 {
584 c.store(true, std::sync::atomic::Ordering::Relaxed);
585 }
586 }
587
588 pub fn chain(self, other: Self) -> VarHandles {
590 VarHandles(smallvec::smallvec![self, other])
591 }
592
593 pub fn downgrade(&self) -> WeakVarHandle {
597 match &self.0 {
598 Some(a) => WeakVarHandle(Arc::downgrade(a)),
599 None => WeakVarHandle::new(),
600 }
601 }
602}
603
604#[derive(Clone, Default)]
606pub struct WeakVarHandle(std::sync::Weak<AtomicBool>);
607impl PartialEq for WeakVarHandle {
608 fn eq(&self, other: &Self) -> bool {
609 self.0.ptr_eq(&other.0)
610 }
611}
612impl Eq for WeakVarHandle {}
613impl fmt::Debug for WeakVarHandle {
614 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
615 f.debug_tuple("WeakVarHandle").finish_non_exhaustive()
616 }
617}
618impl WeakVarHandle {
619 pub fn upgrade(&self) -> Option<VarHandle> {
623 let h = VarHandle(self.0.upgrade());
624 if h.is_dummy() { None } else { Some(h) }
625 }
626
627 pub const fn new() -> Self {
629 WeakVarHandle(std::sync::Weak::new())
630 }
631}
632
633pub(crate) struct VarHandlerOwner(Arc<AtomicBool>);
634impl fmt::Debug for VarHandlerOwner {
635 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
636 write!(f, "{}", Arc::strong_count(&self.0) - 1)?;
637 if self.0.load(std::sync::atomic::Ordering::Relaxed) {
638 write!(f, " perm")
639 } else {
640 Ok(())
641 }
642 }
643}
644impl VarHandlerOwner {
645 pub fn is_alive(&self) -> bool {
646 Arc::strong_count(&self.0) > 1 || self.0.load(std::sync::atomic::Ordering::Relaxed)
647 }
648}
649
650#[must_use = "var handles stops the behavior they represents on drop"]
652#[derive(Clone, Default)]
653pub struct VarHandles(smallvec::SmallVec<[VarHandle; 2]>);
654impl VarHandles {
655 pub const fn dummy() -> Self {
657 VarHandles(smallvec::SmallVec::new_const())
658 }
659
660 pub fn is_dummy(&self) -> bool {
662 self.0.is_empty() || self.0.iter().all(VarHandle::is_dummy)
663 }
664
665 pub fn perm(self) {
667 for handle in self.0 {
668 handle.perm()
669 }
670 }
671
672 pub fn push(&mut self, other: VarHandle) -> &mut Self {
674 if !other.is_dummy() {
675 self.0.push(other);
676 }
677 self
678 }
679
680 pub fn clear(&mut self) {
682 self.0.clear()
683 }
684}
685impl FromIterator<VarHandle> for VarHandles {
686 fn from_iter<T: IntoIterator<Item = VarHandle>>(iter: T) -> Self {
687 VarHandles(iter.into_iter().filter(|h| !h.is_dummy()).collect())
688 }
689}
690impl<const N: usize> From<[VarHandle; N]> for VarHandles {
691 fn from(handles: [VarHandle; N]) -> Self {
692 handles.into_iter().collect()
693 }
694}
695impl Extend<VarHandle> for VarHandles {
696 fn extend<T: IntoIterator<Item = VarHandle>>(&mut self, iter: T) {
697 for handle in iter {
698 self.push(handle);
699 }
700 }
701}
702impl IntoIterator for VarHandles {
703 type Item = VarHandle;
704
705 type IntoIter = smallvec::IntoIter<[VarHandle; 2]>;
706
707 fn into_iter(self) -> Self::IntoIter {
708 self.0.into_iter()
709 }
710}
711impl ops::Deref for VarHandles {
712 type Target = smallvec::SmallVec<[VarHandle; 2]>;
713
714 fn deref(&self) -> &Self::Target {
715 &self.0
716 }
717}
718impl ops::DerefMut for VarHandles {
719 fn deref_mut(&mut self) -> &mut Self::Target {
720 &mut self.0
721 }
722}
723impl From<VarHandle> for VarHandles {
724 fn from(value: VarHandle) -> Self {
725 let mut r = VarHandles::dummy();
726 r.push(value);
727 r
728 }
729}
730
731#[cfg(feature = "type_names")]
732fn value_type_name(var: &dyn VarImpl) -> &'static str {
733 var.value_type_name()
734}
735#[cfg(not(feature = "type_names"))]
736#[inline(always)]
737fn value_type_name(_: &dyn VarImpl) -> &'static str {
738 ""
739}