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 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, MergeInput, MergeVarBuilder, VarMergeInputs, merge_var, merge_var_input, merge_var_output, merge_var_with,
34};
35
36pub(crate) mod response_var;
37pub use response_var::{ResponderVar, Response, ResponseVar, response_done_var, response_var};
38
39pub(crate) mod when_var;
40pub use when_var::{__when_var, AnyWhenVarBuilder, WhenVarBuilder};
41
42pub(crate) mod expr_var;
43pub use expr_var::{__expr_var, expr_var_as, expr_var_into, expr_var_map};
44
45pub(crate) enum DynAnyVar {
46 Const(const_var::ConstVar),
47 Merge(merge_var::MergeVar),
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::Merge($var) => $($tt)+,
65 DynAnyVar::FlatMap($var) => $($tt)+,
66 DynAnyVar::When($var) => $($tt)+,
67
68 DynAnyVar::Shared($var) => $($tt)+,
69 DynAnyVar::Context($var) => $($tt)+,
70 DynAnyVar::Contextual($var) => $($tt)+,
71
72 DynAnyVar::ReadOnlyShared($var) => $($tt)+,
73 DynAnyVar::ReadOnlyFlatMap($var) => $($tt)+,
74 DynAnyVar::ReadOnlyContext($var) => $($tt)+,
75 DynAnyVar::ReadOnlyContextual($var) => $($tt)+,
76 }
77 };
78}
79impl fmt::Debug for DynAnyVar {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 dispatch!(self, v => fmt::Debug::fmt(v, f))
82 }
83}
84
85pub(crate) enum DynWeakAnyVar {
86 Const(const_var::WeakConstVar),
87 Merge(merge_var::WeakMergeVar),
88 When(when_var::WeakWhenVar),
89
90 Shared(shared_var::WeakSharedVar),
91 Context(context_var::ContextVarImpl),
92 FlatMap(flat_map_var::WeakFlatMapVar),
93 Contextual(contextual_var::WeakContextualVar),
94
95 ReadOnlyShared(ReadOnlyImpl<shared_var::WeakSharedVar>),
96 ReadOnlyContext(ReadOnlyImpl<context_var::ContextVarImpl>),
97 ReadOnlyContextual(ReadOnlyImpl<contextual_var::WeakContextualVar>),
98 ReadOnlyFlatMap(ReadOnlyImpl<flat_map_var::WeakFlatMapVar>),
99}
100macro_rules! dispatch_weak {
101 ($self:ident, $var:ident => $($tt:tt)+) => {
102 match $self {
103 DynWeakAnyVar::Const($var) => $($tt)+,
104 DynWeakAnyVar::Shared($var) => $($tt)+,
105 DynWeakAnyVar::Context($var) => $($tt)+,
106 DynWeakAnyVar::Contextual($var) => $($tt)+,
107 DynWeakAnyVar::FlatMap($var) => $($tt)+,
108 DynWeakAnyVar::Merge($var) => $($tt)+,
109 DynWeakAnyVar::When($var) => $($tt)+,
110 DynWeakAnyVar::ReadOnlyShared($var) => $($tt)+,
111 DynWeakAnyVar::ReadOnlyContext($var) => $($tt)+,
112 DynWeakAnyVar::ReadOnlyContextual($var) => $($tt)+,
113 DynWeakAnyVar::ReadOnlyFlatMap($var) => $($tt)+,
114
115 }
116 };
117}
118impl fmt::Debug for DynWeakAnyVar {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 dispatch_weak!(self, v => fmt::Debug::fmt(v, f))
121 }
122}
123
124macro_rules! declare {
125 ($(
126 $(#[$meta:meta])*
127 fn $method:ident(&self $(, $arg:ident : $Input:ty)*) $(-> $Output:ty)?;
128 )+) => {
129 pub(crate) trait VarImpl: fmt::Debug + Any + Send + Sync {
130 $(
131 $(#[$meta])*
132 fn $method(&self $(, $arg: $Input)*) $(-> $Output)?;
133 )+
134 }
135
136 impl VarImpl for DynAnyVar {
137 $(
138 $(#[$meta])*
139 fn $method(&self $(, $arg: $Input)*) $(-> $Output)? {
140 dispatch!(self, v => VarImpl::$method(v$(, $arg)*))
141 }
142 )+
143 }
144 };
145}
146declare! {
147 fn clone_dyn(&self) -> DynAnyVar;
148 fn value_type(&self) -> TypeId;
149 #[cfg(feature = "type_names")]
150 fn value_type_name(&self) -> &'static str;
151 fn strong_count(&self) -> usize;
152 fn var_eq(&self, other: &DynAnyVar) -> bool;
153 fn var_instance_tag(&self) -> VarInstanceTag;
154 fn downgrade(&self) -> DynWeakAnyVar;
155 fn capabilities(&self) -> VarCapability;
156 fn with(&self, visitor: &mut dyn FnMut(&dyn AnyVarValue));
157 fn get(&self) -> BoxAnyVarValue;
158 fn set(&self, new_value: BoxAnyVarValue) -> bool;
159 fn update(&self) -> bool;
160 fn modify(&self, modify: SmallBox<dyn FnMut(&mut AnyVarModify) + Send + 'static, smallbox::space::S4>) -> bool;
161 fn hook(&self, on_new: SmallBox<dyn FnMut(&AnyVarHookArgs) -> bool + Send + 'static, smallbox::space::S4>) -> VarHandle;
162 fn last_update(&self) -> VarUpdateId;
163 fn modify_importance(&self) -> usize;
164 fn is_animating(&self) -> bool;
165 fn hook_animation_stop(&self, handler: AnimationStopFn) -> VarHandle;
166 fn current_context(&self) -> DynAnyVar;
167 fn modify_info(&self) -> ModifyInfo;
168}
169
170macro_rules! declare_weak {
171 ($(
172 fn $method:ident(&self $(, $arg:ident : $Input:ty)*) $(-> $Output:ty)?;
173 )+) => {
174 pub(crate) trait WeakVarImpl: fmt::Debug + Any + Send + Sync {
175 $(
176 fn $method(&self $(, $arg: $Input)*) $(-> $Output)?;
177 )+
178 }
179
180 impl WeakVarImpl for DynWeakAnyVar {
181 $(
182 fn $method(&self $(, $arg: $Input)*) $(-> $Output)? {
183 dispatch_weak!(self, v => WeakVarImpl::$method(v$(, $arg)*))
184 }
185 )+
186 }
187 };
188}
189declare_weak! {
190 fn clone_dyn(&self) -> DynWeakAnyVar;
191 fn strong_count(&self) -> usize;
192 fn upgrade(&self) -> Option<DynAnyVar>;
193 fn var_eq(&self, other: &DynWeakAnyVar) -> bool;
194}
195
196#[derive(Debug, Clone, Copy)]
200#[non_exhaustive]
201pub struct VarIsReadOnlyError {}
202impl fmt::Display for VarIsReadOnlyError {
203 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
204 write!(f, "cannot modify read-only variable")
205 }
206}
207impl std::error::Error for VarIsReadOnlyError {}
208
209bitflags! {
210 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
217 pub struct VarCapability: u8 {
218 const NEW = 0b0000_0010;
225
226 const MODIFY = 0b0000_0011;
235
236 const CONTEXT = 0b1000_0000;
238
239 const MODIFY_CHANGES = 0b0100_0000;
241 const CONTEXT_CHANGES = 0b0010_0000;
243
244 const SHARE = 0b0001_0000;
247 }
248}
249impl VarCapability {
250 pub fn is_const(self) -> bool {
252 self.is_empty()
253 }
254
255 pub fn is_always_read_only(&self) -> bool {
257 !self.contains(Self::MODIFY) && !self.contains(Self::MODIFY_CHANGES)
258 }
259
260 pub fn is_read_only(self) -> bool {
262 !self.can_modify()
263 }
264
265 pub fn can_modify(self) -> bool {
267 self.contains(Self::MODIFY)
268 }
269
270 pub fn is_contextual(self) -> bool {
272 self.contains(Self::CONTEXT)
273 }
274
275 pub fn is_always_contextual(self) -> bool {
277 self.contains(Self::CONTEXT) && !self.contains(Self::CONTEXT_CHANGES)
278 }
279
280 pub fn is_share(&self) -> bool {
282 self.contains(Self::SHARE)
283 }
284
285 pub fn is_local(&self) -> bool {
289 !self.is_share()
290 }
291}
292impl VarCapability {
293 pub(crate) fn as_always_read_only(self) -> Self {
294 let mut out = self;
295
296 out.remove(Self::MODIFY & !Self::NEW);
298 out.remove(Self::MODIFY_CHANGES);
300
301 out
302 }
303}
304
305bitflags! {
306 #[derive(Clone, Copy)]
307 pub(crate) struct VarModifyUpdate: u8 {
308 const UPDATE = 0b001;
310 const REQUESTED = 0b011;
312 const TOUCHED = 0b101;
314 }
315}
316
317pub struct AnyVarModify<'a> {
321 pub(crate) value: &'a mut BoxAnyVarValue,
322 pub(crate) update: VarModifyUpdate,
323 pub(crate) tags: Vec<BoxAnyVarValue>,
324 pub(crate) custom_importance: Option<usize>,
325}
326impl<'a> AnyVarModify<'a> {
327 pub fn set(&mut self, mut new_value: BoxAnyVarValue) -> bool {
331 if **self.value != *new_value {
332 if !self.value.try_swap(&mut *new_value) {
333 #[cfg(feature = "type_names")]
334 panic!(
335 "cannot AnyVarModify::set `{}` on variable of type `{}`",
336 new_value.type_name(),
337 self.value.type_name()
338 );
339 #[cfg(not(feature = "type_names"))]
340 panic!("cannot modify set, type mismatch");
341 }
342 self.update |= VarModifyUpdate::TOUCHED;
343 true
344 } else {
345 false
346 }
347 }
348
349 pub fn update(&mut self) {
351 self.update |= VarModifyUpdate::REQUESTED;
352 }
353
354 pub fn tags(&self) -> &[BoxAnyVarValue] {
359 &self.tags
360 }
361
362 pub fn push_tag(&mut self, tag: impl AnyVarValue) {
364 self.tags.push(BoxAnyVarValue::new(tag));
365 }
366
367 pub fn set_modify_importance(&mut self, importance: usize) {
375 self.custom_importance = Some(importance);
376 }
377
378 pub fn downcast<'s, T: VarValue>(&'s mut self) -> Option<VarModify<'s, 'a, T>> {
380 if self.value.is::<T>() {
381 Some(VarModify {
382 inner: self,
383 _t: PhantomData,
384 })
385 } else {
386 None
387 }
388 }
389
390 pub fn value(&self) -> &dyn AnyVarValue {
394 &**self
395 }
396
397 pub fn value_mut(&mut self) -> &mut dyn AnyVarValue {
403 &mut **self
404 }
405}
406impl<'a> ops::Deref for AnyVarModify<'a> {
407 type Target = dyn AnyVarValue;
408
409 fn deref(&self) -> &Self::Target {
410 &**self.value
411 }
412}
413impl<'a> ops::DerefMut for AnyVarModify<'a> {
414 fn deref_mut(&mut self) -> &mut Self::Target {
415 self.update |= VarModifyUpdate::TOUCHED;
416 self.value.deref_mut()
417 }
418}
419
420pub struct VarModify<'s, 'a, T: VarValue> {
424 inner: &'s mut AnyVarModify<'a>,
425 _t: PhantomData<fn() -> &'a T>,
426}
427impl<'s, 'a, T: VarValue> VarModify<'s, 'a, T> {
428 pub fn set(&mut self, new_value: impl Into<T>) -> bool {
432 let new_value = new_value.into();
433 if **self != new_value {
434 **self = new_value;
435 true
436 } else {
437 false
438 }
439 }
440
441 pub fn update(&mut self) {
443 self.inner.update();
444 }
445
446 pub fn tags(&self) -> &[BoxAnyVarValue] {
451 self.inner.tags()
452 }
453
454 pub fn push_tag(&mut self, tag: impl AnyVarValue) {
456 self.inner.push_tag(tag);
457 }
458
459 pub fn set_modify_importance(&mut self, importance: usize) {
467 self.inner.set_modify_importance(importance);
468 }
469
470 pub fn as_any(&mut self) -> &mut AnyVarModify<'a> {
472 self.inner
473 }
474
475 pub fn value(&self) -> &T {
479 self
480 }
481
482 pub fn value_mut(&mut self) -> &mut T {
488 self
489 }
490}
491impl<'s, 'a, T: VarValue> ops::Deref for VarModify<'s, 'a, T> {
492 type Target = T;
493
494 fn deref(&self) -> &Self::Target {
495 self.inner.downcast_ref().unwrap()
496 }
497}
498impl<'s, 'a, T: VarValue> ops::DerefMut for VarModify<'s, 'a, T> {
499 fn deref_mut(&mut self) -> &mut Self::Target {
500 self.inner.downcast_mut().unwrap()
501 }
502}
503
504#[derive(Clone, Default)]
512#[must_use = "var handle stops the behavior it represents on drop"]
513pub struct VarHandle(Option<Arc<AtomicBool>>);
514impl PartialEq for VarHandle {
515 fn eq(&self, other: &Self) -> bool {
516 if let Some(a) = &self.0
517 && let Some(b) = &other.0
518 {
519 Arc::ptr_eq(a, b)
520 } else {
521 false
522 }
523 }
524}
525impl fmt::Debug for VarHandle {
526 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
527 if self.is_dummy() {
528 write!(f, "VarHandle(<dummy>)")
529 } else {
530 f.debug_tuple("VarHandle").finish_non_exhaustive()
531 }
532 }
533}
534impl VarHandle {
535 pub const fn dummy() -> Self {
537 VarHandle(None)
538 }
539
540 pub(crate) fn new() -> (VarHandlerOwner, Self) {
541 let h = Arc::new(AtomicBool::new(false));
542 (VarHandlerOwner(h.clone()), Self(Some(h)))
543 }
544
545 pub fn is_dummy(&self) -> bool {
549 self.0.is_none()
550 }
551
552 pub fn perm(self) {
556 if let Some(c) = &self.0 {
557 c.store(true, std::sync::atomic::Ordering::Relaxed);
558 }
559 }
560
561 pub fn chain(self, other: Self) -> VarHandles {
563 VarHandles(smallvec::smallvec![self, other])
564 }
565
566 pub fn downgrade(&self) -> WeakVarHandle {
570 match &self.0 {
571 Some(a) => WeakVarHandle(Arc::downgrade(a)),
572 None => WeakVarHandle::new(),
573 }
574 }
575}
576
577#[derive(Clone, Default)]
579pub struct WeakVarHandle(std::sync::Weak<AtomicBool>);
580impl PartialEq for WeakVarHandle {
581 fn eq(&self, other: &Self) -> bool {
582 self.0.ptr_eq(&other.0)
583 }
584}
585impl Eq for WeakVarHandle {}
586impl fmt::Debug for WeakVarHandle {
587 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
588 f.debug_tuple("WeakVarHandle").finish_non_exhaustive()
589 }
590}
591impl WeakVarHandle {
592 pub fn upgrade(&self) -> Option<VarHandle> {
596 let h = VarHandle(self.0.upgrade());
597 if h.is_dummy() { None } else { Some(h) }
598 }
599
600 pub const fn new() -> Self {
602 WeakVarHandle(std::sync::Weak::new())
603 }
604}
605
606pub(crate) struct VarHandlerOwner(Arc<AtomicBool>);
607impl fmt::Debug for VarHandlerOwner {
608 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
609 write!(f, "{}", Arc::strong_count(&self.0) - 1)?;
610 if self.0.load(std::sync::atomic::Ordering::Relaxed) {
611 write!(f, " perm")
612 } else {
613 Ok(())
614 }
615 }
616}
617impl VarHandlerOwner {
618 pub fn is_alive(&self) -> bool {
619 Arc::strong_count(&self.0) > 1 || self.0.load(std::sync::atomic::Ordering::Relaxed)
620 }
621}
622
623#[must_use = "var handles stops the behavior they represents on drop"]
625#[derive(Clone, Default)]
626pub struct VarHandles(smallvec::SmallVec<[VarHandle; 2]>);
627impl VarHandles {
628 pub const fn dummy() -> Self {
630 VarHandles(smallvec::SmallVec::new_const())
631 }
632
633 pub fn is_dummy(&self) -> bool {
635 self.0.is_empty() || self.0.iter().all(VarHandle::is_dummy)
636 }
637
638 pub fn perm(self) {
640 for handle in self.0 {
641 handle.perm()
642 }
643 }
644
645 pub fn push(&mut self, other: VarHandle) -> &mut Self {
647 if !other.is_dummy() {
648 self.0.push(other);
649 }
650 self
651 }
652
653 pub fn clear(&mut self) {
655 self.0.clear()
656 }
657}
658impl FromIterator<VarHandle> for VarHandles {
659 fn from_iter<T: IntoIterator<Item = VarHandle>>(iter: T) -> Self {
660 VarHandles(iter.into_iter().filter(|h| !h.is_dummy()).collect())
661 }
662}
663impl<const N: usize> From<[VarHandle; N]> for VarHandles {
664 fn from(handles: [VarHandle; N]) -> Self {
665 handles.into_iter().collect()
666 }
667}
668impl Extend<VarHandle> for VarHandles {
669 fn extend<T: IntoIterator<Item = VarHandle>>(&mut self, iter: T) {
670 for handle in iter {
671 self.push(handle);
672 }
673 }
674}
675impl IntoIterator for VarHandles {
676 type Item = VarHandle;
677
678 type IntoIter = smallvec::IntoIter<[VarHandle; 2]>;
679
680 fn into_iter(self) -> Self::IntoIter {
681 self.0.into_iter()
682 }
683}
684impl ops::Deref for VarHandles {
685 type Target = smallvec::SmallVec<[VarHandle; 2]>;
686
687 fn deref(&self) -> &Self::Target {
688 &self.0
689 }
690}
691impl ops::DerefMut for VarHandles {
692 fn deref_mut(&mut self) -> &mut Self::Target {
693 &mut self.0
694 }
695}
696impl From<VarHandle> for VarHandles {
697 fn from(value: VarHandle) -> Self {
698 let mut r = VarHandles::dummy();
699 r.push(value);
700 r
701 }
702}
703
704#[cfg(feature = "type_names")]
705fn value_type_name(var: &dyn VarImpl) -> &'static str {
706 var.value_type_name()
707}
708#[cfg(not(feature = "type_names"))]
709#[inline(always)]
710fn value_type_name(_: &dyn VarImpl) -> &'static str {
711 ""
712}