Skip to main content

zng_var/
var_impl.rs

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/// Error when an attempt to modify a variable without the [`MODIFY`] capability is made.
194///
195/// [`MODIFY`]: VarCapability::MODIFY
196#[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    /// Kinds of interactions allowed by a [`Var<T>`] in the current update.
208    ///
209    /// You can get the current capabilities of a var by using the [`AnyVar::capabilities`] method.
210    ///
211    /// [`Var<T>`]: crate::Var
212    /// [`AnyVar::capabilities`]: crate::AnyVar::capabilities
213    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
214    pub struct VarCapability: u8 {
215        /// Variable value can change.
216        ///
217        /// If this is set the [`AnyVar::is_new`] can be `true` in some updates, a variable can `NEW`
218        /// even if it cannot `MODIFY`, in this case the variable is a read-only wrapper on a read-write variable.
219        ///
220        /// [`AnyVar::is_new`]: crate::AnyVar::is_new
221        const NEW = 0b0000_0010;
222
223        /// Variable can be modified.
224        ///
225        /// If this is set [`Var::try_modify`] always returns `Ok`, if this is set `NEW` is also set.
226        ///
227        /// Note that modify requests from inside overridden animations can still be ignored, see [`AnyVar::modify_importance`].
228        ///
229        /// [`AnyVar::modify_importance`]: crate::AnyVar::modify_importance
230        /// [`Var::try_modify`]: crate::Var::try_modify
231        const MODIFY = 0b0000_0011;
232
233        /// Var represents different inner variables depending on the context it is used.
234        const CONTEXT = 0b1000_0000;
235
236        /// Variable capabilities can change to sometimes have the `MODIFY` capability.
237        const MODIFY_CHANGES = 0b0100_0000;
238        /// Variable capabilities can change to sometimes have the `CONTEXT` capability.
239        const CONTEXT_CHANGES = 0b0010_0000;
240
241        /// Var is an *arc* reference to the value and variable state, cloning the variable only clones a
242        /// reference to the variable, all references modify and notify the same state.
243        const SHARE = 0b0001_0000;
244    }
245}
246impl VarCapability {
247    /// If cannot `NEW` and is not `MODIFY_CHANGES`.
248    pub fn is_const(self) -> bool {
249        self.is_empty()
250    }
251
252    /// If does not have `MODIFY` capability and is not `MODIFY_CHANGES`.
253    pub fn is_always_read_only(&self) -> bool {
254        !self.contains(Self::MODIFY) && !self.contains(Self::MODIFY_CHANGES)
255    }
256
257    /// If does not have `MODIFY` capability.
258    pub fn is_read_only(self) -> bool {
259        !self.can_modify()
260    }
261
262    /// Has the `MODIFY` capability.
263    pub fn can_modify(self) -> bool {
264        self.contains(Self::MODIFY)
265    }
266
267    /// Has the `CONTEXT` capability.
268    pub fn is_contextual(self) -> bool {
269        self.contains(Self::CONTEXT)
270    }
271
272    /// Has the `CONTEXT` capability and does not have `CONTEXT_CHANGES`.
273    pub fn is_always_contextual(self) -> bool {
274        self.contains(Self::CONTEXT) && !self.contains(Self::CONTEXT_CHANGES)
275    }
276
277    /// Has the `SHARE` capability.
278    pub fn is_share(&self) -> bool {
279        self.contains(Self::SHARE)
280    }
281
282    /// Does not have the `SHARE` capability.
283    ///
284    /// Cloning this variable clones the value.
285    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        // can be new, but not modify
294        out.remove(Self::MODIFY & !Self::NEW);
295        // never will allow modify
296        out.remove(Self::MODIFY_CHANGES);
297
298        out
299    }
300}
301
302bitflags! {
303    #[derive(Clone, Copy)]
304    pub(crate) struct VarModifyUpdate: u8 {
305        /// Value was deref_mut or update was called
306        const UPDATE = 0b001;
307        /// Method update was called
308        const REQUESTED = 0b011;
309        /// Value was deref_mut
310        const TOUCHED = 0b101;
311    }
312}
313
314/// Mutable reference to a variable value.
315///
316/// The variable will notify an update only on `deref_mut`.
317pub 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    /// Replace the value if not equal.
325    ///
326    /// Note that you can also deref_mut to modify the value.
327    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    /// Notify an update, even if the value does not actually change.
347    pub fn update(&mut self) {
348        self.update |= VarModifyUpdate::REQUESTED;
349    }
350
351    /// Custom tags that will be shared with the var hooks if the value updates.
352    ///
353    /// The tags where set by previous modify closures or this one during this update cycle, so
354    /// tags can also be used to communicate between modify closures.
355    pub fn tags(&self) -> &[BoxAnyVarValue] {
356        &self.tags
357    }
358
359    /// Add a custom tag object that will be shared with the var hooks if the value updates.
360    pub fn push_tag(&mut self, tag: impl AnyVarValue) {
361        self.tags.push(BoxAnyVarValue::new(tag));
362    }
363
364    /// Sets a custom [`AnyVar::modify_importance`] value.
365    ///
366    /// Note that the modify info is already automatically set, using a custom value here
367    /// can easily break all future modify requests for this variable. The importance is set even if the
368    /// variable does not update (no actual value change or update request).
369    ///
370    /// [`AnyVar::modify_importance`]: crate::AnyVar::modify_importance
371    pub fn set_modify_importance(&mut self, importance: usize) {
372        self.custom_importance = Some(importance);
373    }
374
375    /// Strongly typed reference, if it is of the same type.
376    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    /// Immutable reference to the value.
388    ///
389    /// Note that you can also simply deref to the value.
390    pub fn value(&self) -> &dyn AnyVarValue {
391        &**self
392    }
393
394    /// Mutable reference to the value.
395    ///
396    /// Getting a mutable reference to the value flags the variable to notify update.
397    ///
398    /// Note that you can also simply deref to the value.
399    pub fn value_mut(&mut self) -> &mut dyn AnyVarValue {
400        &mut **self
401    }
402
403    /// Call `f` and check if it touched the value ([`value_mut`] or [`deref_mut`]),
404    /// changed it ([`set`] returns `true`) or requested [`update`].
405    ///
406    /// [`value_mut`]: Self::value_mut
407    /// [`set`]: Self::set
408    /// [`update`]: Self::update
409    /// [`deref_mut`]: ops::DerefMut::deref_mut
410    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
432/// Mutable reference to a variable value.
433///
434/// The variable will notify an update only on `deref_mut`.
435pub 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    /// Replace the value if not equal.
441    ///
442    /// Note that you can also deref_mut to modify the value.
443    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    /// Notify an update, even if the value does not actually change.
454    pub fn update(&mut self) {
455        self.inner.update();
456    }
457
458    /// Custom tags that will be shared with the var hooks if the value updates.
459    ///
460    /// The tags where set by previous modify closures or this one during this update cycle, so
461    /// tags can also be used to communicate between modify closures.
462    pub fn tags(&self) -> &[BoxAnyVarValue] {
463        self.inner.tags()
464    }
465
466    /// Add a custom tag object that will be shared with the var hooks if the value updates.
467    pub fn push_tag(&mut self, tag: impl AnyVarValue) {
468        self.inner.push_tag(tag);
469    }
470
471    /// Sets a custom [`AnyVar::modify_importance`] value.
472    ///
473    /// Note that the modify info is already automatically set, using a custom value here
474    /// can easily break all future modify requests for this variable. The importance is set even if the
475    /// variable does not update (no actual value change or update request).
476    ///
477    /// [`AnyVar::modify_importance`]: crate::AnyVar::modify_importance
478    pub fn set_modify_importance(&mut self, importance: usize) {
479        self.inner.set_modify_importance(importance);
480    }
481
482    /// Type erased reference.
483    pub fn as_any(&mut self) -> &mut AnyVarModify<'a> {
484        self.inner
485    }
486
487    /// Immutable reference to the value.
488    ///
489    /// Note that you can also simply deref to the value.
490    pub fn value(&self) -> &T {
491        self
492    }
493
494    /// Mutable reference to the value.
495    ///
496    /// Getting a mutable reference to the value flags the variable to notify update.
497    ///
498    /// Note that you can also simply deref to the value.
499    pub fn value_mut(&mut self) -> &mut T {
500        self
501    }
502
503    /// Call `f` and check if it touched the value ([`value_mut`] or [`deref_mut`]),
504    /// changed it ([`set`] returns `true`) or requested [`update`].
505    ///
506    /// [`value_mut`]: Self::value_mut
507    /// [`set`]: Self::set
508    /// [`update`]: Self::update
509    /// [`deref_mut`]: ops::DerefMut::deref_mut
510    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/// Handle to a variable or animation hook.
532///
533/// This can represent a widget subscriber, a var binding, var app handler or animation, dropping the handler stops
534/// the behavior it represents.
535///
536/// Note that the hook closure is not dropped immediately when the handle is dropped, usually it will drop only the next
537/// time it would have been called.
538#[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    /// Handle to no variable.
563    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    /// Returns `true` if the handle is a [`dummy`].
573    ///
574    /// [`dummy`]: VarHandle::dummy
575    pub fn is_dummy(&self) -> bool {
576        self.0.is_none()
577    }
578
579    /// Drop the handle without stopping the behavior it represents.
580    ///
581    /// Note that the behavior can still be stopped by dropping the involved variables.
582    pub fn perm(self) {
583        if let Some(c) = &self.0 {
584            c.store(true, std::sync::atomic::Ordering::Relaxed);
585        }
586    }
587
588    /// Create a [`VarHandles`] collection with `self` and `other`.
589    pub fn chain(self, other: Self) -> VarHandles {
590        VarHandles(smallvec::smallvec![self, other])
591    }
592
593    /// Create a weak reference to this handle.
594    ///
595    /// Note that weak references to dummy handles cannot upgrade back.
596    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/// Weak reference to a [`VarHandle`].
605#[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    /// Upgrade to strong handle.
620    ///
621    /// Returns `None` if no strong reference to the handle remains.
622    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    /// New dummy weak reference that does not upgrade.
628    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/// Represents a collection of var handles.
651#[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    /// Empty collection.
656    pub const fn dummy() -> Self {
657        VarHandles(smallvec::SmallVec::new_const())
658    }
659
660    /// Returns `true` if empty or all handles are dummy.
661    pub fn is_dummy(&self) -> bool {
662        self.0.is_empty() || self.0.iter().all(VarHandle::is_dummy)
663    }
664
665    /// Drop all handles without stopping their behavior.
666    pub fn perm(self) {
667        for handle in self.0 {
668            handle.perm()
669        }
670    }
671
672    /// Add the `other` handle to the collection, if it is not dummy.
673    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    /// Drop all handles.
681    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}