1use std::{
2 any::{Any, TypeId},
3 fmt,
4 marker::PhantomData,
5 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(crate) mod cow_var;
22pub use const_var::IntoVar;
23pub(crate) mod flat_map_var;
24pub(crate) mod read_only_var;
25
26pub(crate) mod contextual_var;
27pub use contextual_var::{ContextInitHandle, WeakContextInitHandle, any_contextual_var, contextual_var};
28
29pub(crate) mod context_var;
30pub use context_var::{__context_var_local, ContextVar, context_var_init};
31
32pub(crate) mod merge_var;
33pub use merge_var::{
34 __merge_var, MergeInput, MergeVarBuilder, VarMergeInputs, merge_var, merge_var_input, merge_var_output, 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 Merge(merge_var::MergeVar),
49 When(when_var::WhenVar),
50
51 Shared(shared_var::SharedVar),
52 Context(context_var::ContextVarImpl),
53 FlatMap(flat_map_var::FlatMapVar),
54 Cow(cow_var::CowVar),
55 Contextual(contextual_var::ContextualVar),
56
57 ReadOnlyShared(ReadOnlyImpl<shared_var::SharedVar>),
58 ReadOnlyFlatMap(ReadOnlyImpl<flat_map_var::FlatMapVar>),
59 ReadOnlyContext(ReadOnlyImpl<context_var::ContextVarImpl>),
60 ReadOnlyCow(ReadOnlyImpl<cow_var::CowVar>),
61 ReadOnlyContextual(ReadOnlyImpl<contextual_var::ContextualVar>),
62}
63macro_rules! dispatch {
64 ($self:ident, $var:ident => $($tt:tt)+) => {
65 match $self {
66 DynAnyVar::Const($var) => $($tt)+,
67 DynAnyVar::Merge($var) => $($tt)+,
68 DynAnyVar::FlatMap($var) => $($tt)+,
69 DynAnyVar::When($var) => $($tt)+,
70
71 DynAnyVar::Shared($var) => $($tt)+,
72 DynAnyVar::Context($var) => $($tt)+,
73 DynAnyVar::Cow($var) => $($tt)+,
74 DynAnyVar::Contextual($var) => $($tt)+,
75
76 DynAnyVar::ReadOnlyShared($var) => $($tt)+,
77 DynAnyVar::ReadOnlyFlatMap($var) => $($tt)+,
78 DynAnyVar::ReadOnlyContext($var) => $($tt)+,
79 DynAnyVar::ReadOnlyCow($var) => $($tt)+,
80 DynAnyVar::ReadOnlyContextual($var) => $($tt)+,
81 }
82 };
83}
84impl fmt::Debug for DynAnyVar {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 dispatch!(self, v => fmt::Debug::fmt(v, f))
87 }
88}
89
90pub(crate) enum DynWeakAnyVar {
91 Const(const_var::WeakConstVar),
92 Merge(merge_var::WeakMergeVar),
93 When(when_var::WeakWhenVar),
94
95 Shared(shared_var::WeakSharedVar),
96 Context(context_var::ContextVarImpl),
97 FlatMap(flat_map_var::WeakFlatMapVar),
98 Cow(cow_var::WeakCowVar),
99 Contextual(contextual_var::WeakContextualVar),
100
101 ReadOnlyShared(ReadOnlyImpl<shared_var::WeakSharedVar>),
102 ReadOnlyContext(ReadOnlyImpl<context_var::ContextVarImpl>),
103 ReadOnlyCow(ReadOnlyImpl<cow_var::WeakCowVar>),
104 ReadOnlyContextual(ReadOnlyImpl<contextual_var::WeakContextualVar>),
105 ReadOnlyFlatMap(ReadOnlyImpl<flat_map_var::WeakFlatMapVar>),
106}
107macro_rules! dispatch_weak {
108 ($self:ident, $var:ident => $($tt:tt)+) => {
109 match $self {
110 DynWeakAnyVar::Const($var) => $($tt)+,
111 DynWeakAnyVar::Shared($var) => $($tt)+,
112 DynWeakAnyVar::Context($var) => $($tt)+,
113 DynWeakAnyVar::Cow($var) => $($tt)+,
114 DynWeakAnyVar::Contextual($var) => $($tt)+,
115 DynWeakAnyVar::FlatMap($var) => $($tt)+,
116 DynWeakAnyVar::Merge($var) => $($tt)+,
117 DynWeakAnyVar::When($var) => $($tt)+,
118 DynWeakAnyVar::ReadOnlyShared($var) => $($tt)+,
119 DynWeakAnyVar::ReadOnlyContext($var) => $($tt)+,
120 DynWeakAnyVar::ReadOnlyCow($var) => $($tt)+,
121 DynWeakAnyVar::ReadOnlyContextual($var) => $($tt)+,
122 DynWeakAnyVar::ReadOnlyFlatMap($var) => $($tt)+,
123
124 }
125 };
126}
127impl fmt::Debug for DynWeakAnyVar {
128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129 dispatch_weak!(self, v => fmt::Debug::fmt(v, f))
130 }
131}
132
133macro_rules! declare {
134 ($(
135 $(#[$meta:meta])*
136 fn $method:ident(&self $(, $arg:ident : $Input:ty)*) $(-> $Output:ty)?;
137 )+) => {
138 pub(crate) trait VarImpl: fmt::Debug + Any + Send + Sync {
139 $(
140 $(#[$meta])*
141 fn $method(&self $(, $arg: $Input)*) $(-> $Output)?;
142 )+
143 }
144
145 impl VarImpl for DynAnyVar {
146 $(
147 $(#[$meta])*
148 fn $method(&self $(, $arg: $Input)*) $(-> $Output)? {
149 dispatch!(self, v => VarImpl::$method(v$(, $arg)*))
150 }
151 )+
152 }
153 };
154}
155declare! {
156 fn clone_dyn(&self) -> DynAnyVar;
157 fn value_type(&self) -> TypeId;
158 #[cfg(feature = "type_names")]
159 fn value_type_name(&self) -> &'static str;
160 fn strong_count(&self) -> usize;
161 fn var_eq(&self, other: &DynAnyVar) -> bool;
162 fn var_instance_tag(&self) -> VarInstanceTag;
163 fn downgrade(&self) -> DynWeakAnyVar;
164 fn capabilities(&self) -> VarCapability;
165 fn with(&self, visitor: &mut dyn FnMut(&dyn AnyVarValue));
166 fn get(&self) -> BoxAnyVarValue;
167 fn set(&self, new_value: BoxAnyVarValue) -> bool;
168 fn update(&self) -> bool;
169 fn modify(&self, modify: SmallBox<dyn FnMut(&mut AnyVarModify) + Send + 'static, smallbox::space::S4>) -> bool;
170 fn hook(&self, on_new: SmallBox<dyn FnMut(&AnyVarHookArgs) -> bool + Send + 'static, smallbox::space::S4>) -> VarHandle;
171 fn last_update(&self) -> VarUpdateId;
172 fn modify_importance(&self) -> usize;
173 fn is_animating(&self) -> bool;
174 fn hook_animation_stop(&self, handler: AnimationStopFn) -> VarHandle;
175 fn current_context(&self) -> DynAnyVar;
176 fn modify_info(&self) -> ModifyInfo;
177}
178
179macro_rules! declare_weak {
180 ($(
181 fn $method:ident(&self $(, $arg:ident : $Input:ty)*) $(-> $Output:ty)?;
182 )+) => {
183 pub(crate) trait WeakVarImpl: fmt::Debug + Any + Send + Sync {
184 $(
185 fn $method(&self $(, $arg: $Input)*) $(-> $Output)?;
186 )+
187 }
188
189 impl WeakVarImpl for DynWeakAnyVar {
190 $(
191 fn $method(&self $(, $arg: $Input)*) $(-> $Output)? {
192 dispatch_weak!(self, v => WeakVarImpl::$method(v$(, $arg)*))
193 }
194 )+
195 }
196 };
197}
198declare_weak! {
199 fn clone_dyn(&self) -> DynWeakAnyVar;
200 fn strong_count(&self) -> usize;
201 fn upgrade(&self) -> Option<DynAnyVar>;
202 fn var_eq(&self, other: &DynWeakAnyVar) -> bool;
203}
204
205#[derive(Debug, Clone, Copy)]
209#[non_exhaustive]
210pub struct VarIsReadOnlyError {}
211impl fmt::Display for VarIsReadOnlyError {
212 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
213 write!(f, "cannot modify read-only variable")
214 }
215}
216impl std::error::Error for VarIsReadOnlyError {}
217
218bitflags! {
219 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
226 pub struct VarCapability: u8 {
227 const NEW = 0b0000_0010;
234
235 const MODIFY = 0b0000_0011;
244
245 const CONTEXT = 0b1000_0000;
247
248 const MODIFY_CHANGES = 0b0100_0000;
250 const CONTEXT_CHANGES = 0b0010_0000;
252
253 const SHARE = 0b0001_0000;
256 }
257}
258impl VarCapability {
259 pub fn is_const(self) -> bool {
261 self.is_empty()
262 }
263
264 pub fn is_always_read_only(&self) -> bool {
266 !self.contains(Self::MODIFY) && !self.contains(Self::MODIFY_CHANGES)
267 }
268
269 pub fn is_read_only(self) -> bool {
271 !self.can_modify()
272 }
273
274 pub fn can_modify(self) -> bool {
276 self.contains(Self::MODIFY)
277 }
278
279 pub fn is_contextual(self) -> bool {
281 self.contains(Self::CONTEXT)
282 }
283
284 pub fn is_always_contextual(self) -> bool {
286 self.contains(Self::CONTEXT) && !self.contains(Self::CONTEXT_CHANGES)
287 }
288
289 pub fn is_share(&self) -> bool {
291 self.contains(Self::SHARE)
292 }
293
294 pub fn is_local(&self) -> bool {
298 !self.is_share()
299 }
300}
301impl VarCapability {
302 pub(crate) fn as_always_read_only(self) -> Self {
303 let mut out = self;
304
305 out.remove(Self::MODIFY & !Self::NEW);
307 out.remove(Self::MODIFY_CHANGES);
309
310 out
311 }
312}
313
314bitflags! {
315 #[derive(Clone, Copy)]
316 pub(crate) struct VarModifyUpdate: u8 {
317 const UPDATE = 0b001;
319 const REQUESTED = 0b011;
321 const TOUCHED = 0b101;
323 }
324}
325
326pub struct AnyVarModify<'a> {
330 pub(crate) value: &'a mut BoxAnyVarValue,
331 pub(crate) update: VarModifyUpdate,
332 pub(crate) tags: Vec<BoxAnyVarValue>,
333 pub(crate) custom_importance: Option<usize>,
334}
335impl<'a> AnyVarModify<'a> {
336 pub fn set(&mut self, mut new_value: BoxAnyVarValue) -> bool {
340 if **self.value != *new_value {
341 if !self.value.try_swap(&mut *new_value) {
342 #[cfg(feature = "type_names")]
343 panic!(
344 "cannot AnyVarModify::set `{}` on variable of type `{}`",
345 new_value.type_name(),
346 self.value.type_name()
347 );
348 #[cfg(not(feature = "type_names"))]
349 panic!("cannot modify set, type mismatch");
350 }
351 self.update |= VarModifyUpdate::TOUCHED;
352 true
353 } else {
354 false
355 }
356 }
357
358 pub fn update(&mut self) {
360 self.update |= VarModifyUpdate::REQUESTED;
361 }
362
363 pub fn tags(&self) -> &[BoxAnyVarValue] {
368 &self.tags
369 }
370
371 pub fn push_tag(&mut self, tag: impl AnyVarValue) {
373 self.tags.push(BoxAnyVarValue::new(tag));
374 }
375
376 pub fn set_modify_importance(&mut self, importance: usize) {
384 self.custom_importance = Some(importance);
385 }
386
387 pub fn downcast<'s, T: VarValue>(&'s mut self) -> Option<VarModify<'s, 'a, T>> {
389 if self.value.is::<T>() {
390 Some(VarModify {
391 inner: self,
392 _t: PhantomData,
393 })
394 } else {
395 None
396 }
397 }
398
399 pub fn value(&self) -> &dyn AnyVarValue {
403 &**self
404 }
405
406 pub fn value_mut(&mut self) -> &mut dyn AnyVarValue {
412 &mut **self
413 }
414}
415impl<'a> ops::Deref for AnyVarModify<'a> {
416 type Target = dyn AnyVarValue;
417
418 fn deref(&self) -> &Self::Target {
419 &**self.value
420 }
421}
422impl<'a> ops::DerefMut for AnyVarModify<'a> {
423 fn deref_mut(&mut self) -> &mut Self::Target {
424 self.update |= VarModifyUpdate::TOUCHED;
425 self.value.deref_mut()
426 }
427}
428
429pub struct VarModify<'s, 'a, T: VarValue> {
433 inner: &'s mut AnyVarModify<'a>,
434 _t: PhantomData<fn() -> &'a T>,
435}
436impl<'s, 'a, T: VarValue> VarModify<'s, 'a, T> {
437 pub fn set(&mut self, new_value: impl Into<T>) -> bool {
441 let new_value = new_value.into();
442 if **self != new_value {
443 **self = new_value;
444 true
445 } else {
446 false
447 }
448 }
449
450 pub fn update(&mut self) {
452 self.inner.update();
453 }
454
455 pub fn tags(&self) -> &[BoxAnyVarValue] {
460 self.inner.tags()
461 }
462
463 pub fn push_tag(&mut self, tag: impl AnyVarValue) {
465 self.inner.push_tag(tag);
466 }
467
468 pub fn set_modify_importance(&mut self, importance: usize) {
476 self.inner.set_modify_importance(importance);
477 }
478
479 pub fn as_any(&mut self) -> &mut AnyVarModify<'a> {
481 self.inner
482 }
483
484 pub fn value(&self) -> &T {
488 self
489 }
490
491 pub fn value_mut(&mut self) -> &mut T {
497 self
498 }
499}
500impl<'s, 'a, T: VarValue> ops::Deref for VarModify<'s, 'a, T> {
501 type Target = T;
502
503 fn deref(&self) -> &Self::Target {
504 self.inner.downcast_ref().unwrap()
505 }
506}
507impl<'s, 'a, T: VarValue> ops::DerefMut for VarModify<'s, 'a, T> {
508 fn deref_mut(&mut self) -> &mut Self::Target {
509 self.inner.downcast_mut().unwrap()
510 }
511}
512
513#[derive(Clone, Default)]
521#[must_use = "var handle stops the behavior it represents on drop"]
522pub struct VarHandle(Option<Arc<AtomicBool>>);
523impl PartialEq for VarHandle {
524 fn eq(&self, other: &Self) -> bool {
525 if let Some(a) = &self.0
526 && let Some(b) = &other.0
527 {
528 Arc::ptr_eq(a, b)
529 } else {
530 false
531 }
532 }
533}
534impl fmt::Debug for VarHandle {
535 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
536 if self.is_dummy() {
537 write!(f, "VarHandle(<dummy>)")
538 } else {
539 f.debug_tuple("VarHandle").finish_non_exhaustive()
540 }
541 }
542}
543impl VarHandle {
544 pub const fn dummy() -> Self {
546 VarHandle(None)
547 }
548
549 pub(crate) fn new() -> (VarHandlerOwner, Self) {
550 let h = Arc::new(AtomicBool::new(false));
551 (VarHandlerOwner(h.clone()), Self(Some(h)))
552 }
553
554 pub fn is_dummy(&self) -> bool {
558 self.0.is_none()
559 }
560
561 pub fn perm(self) {
565 if let Some(c) = &self.0 {
566 c.store(true, std::sync::atomic::Ordering::Relaxed);
567 }
568 }
569
570 pub fn chain(self, other: Self) -> VarHandles {
572 VarHandles(smallvec::smallvec![self, other])
573 }
574
575 pub fn downgrade(&self) -> WeakVarHandle {
579 match &self.0 {
580 Some(a) => WeakVarHandle(Arc::downgrade(a)),
581 None => WeakVarHandle::new(),
582 }
583 }
584}
585
586#[derive(Clone, Default)]
588pub struct WeakVarHandle(std::sync::Weak<AtomicBool>);
589impl PartialEq for WeakVarHandle {
590 fn eq(&self, other: &Self) -> bool {
591 self.0.ptr_eq(&other.0)
592 }
593}
594impl Eq for WeakVarHandle {}
595impl fmt::Debug for WeakVarHandle {
596 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
597 f.debug_tuple("WeakVarHandle").finish_non_exhaustive()
598 }
599}
600impl WeakVarHandle {
601 pub fn upgrade(&self) -> Option<VarHandle> {
605 let h = VarHandle(self.0.upgrade());
606 if h.is_dummy() { None } else { Some(h) }
607 }
608
609 pub const fn new() -> Self {
611 WeakVarHandle(std::sync::Weak::new())
612 }
613}
614
615pub(crate) struct VarHandlerOwner(Arc<AtomicBool>);
616impl fmt::Debug for VarHandlerOwner {
617 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
618 write!(f, "{}", Arc::strong_count(&self.0) - 1)?;
619 if self.0.load(std::sync::atomic::Ordering::Relaxed) {
620 write!(f, " perm")
621 } else {
622 Ok(())
623 }
624 }
625}
626impl VarHandlerOwner {
627 pub fn is_alive(&self) -> bool {
628 Arc::strong_count(&self.0) > 1 || self.0.load(std::sync::atomic::Ordering::Relaxed)
629 }
630}
631
632#[must_use = "var handles stops the behavior they represents on drop"]
634#[derive(Clone, Default)]
635pub struct VarHandles(smallvec::SmallVec<[VarHandle; 2]>);
636impl VarHandles {
637 pub const fn dummy() -> Self {
639 VarHandles(smallvec::SmallVec::new_const())
640 }
641
642 pub fn is_dummy(&self) -> bool {
644 self.0.is_empty() || self.0.iter().all(VarHandle::is_dummy)
645 }
646
647 pub fn perm(self) {
649 for handle in self.0 {
650 handle.perm()
651 }
652 }
653
654 pub fn push(&mut self, other: VarHandle) -> &mut Self {
656 if !other.is_dummy() {
657 self.0.push(other);
658 }
659 self
660 }
661
662 pub fn clear(&mut self) {
664 self.0.clear()
665 }
666}
667impl FromIterator<VarHandle> for VarHandles {
668 fn from_iter<T: IntoIterator<Item = VarHandle>>(iter: T) -> Self {
669 VarHandles(iter.into_iter().filter(|h| !h.is_dummy()).collect())
670 }
671}
672impl<const N: usize> From<[VarHandle; N]> for VarHandles {
673 fn from(handles: [VarHandle; N]) -> Self {
674 handles.into_iter().collect()
675 }
676}
677impl Extend<VarHandle> for VarHandles {
678 fn extend<T: IntoIterator<Item = VarHandle>>(&mut self, iter: T) {
679 for handle in iter {
680 self.push(handle);
681 }
682 }
683}
684impl IntoIterator for VarHandles {
685 type Item = VarHandle;
686
687 type IntoIter = smallvec::IntoIter<[VarHandle; 2]>;
688
689 fn into_iter(self) -> Self::IntoIter {
690 self.0.into_iter()
691 }
692}
693impl ops::Deref for VarHandles {
694 type Target = smallvec::SmallVec<[VarHandle; 2]>;
695
696 fn deref(&self) -> &Self::Target {
697 &self.0
698 }
699}
700impl ops::DerefMut for VarHandles {
701 fn deref_mut(&mut self) -> &mut Self::Target {
702 &mut self.0
703 }
704}
705impl From<VarHandle> for VarHandles {
706 fn from(value: VarHandle) -> Self {
707 let mut r = VarHandles::dummy();
708 r.push(value);
709 r
710 }
711}
712
713#[cfg(feature = "type_names")]
714fn value_type_name(var: &dyn VarImpl) -> &'static str {
715 var.value_type_name()
716}
717#[cfg(not(feature = "type_names"))]
718#[inline(always)]
719fn value_type_name(_: &dyn VarImpl) -> &'static str {
720 ""
721}