zng_var/
var_impl.rs

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/// Error when an attempt to modify a variable without the [`MODIFY`] capability is made.
206///
207/// [`MODIFY`]: VarCapability::MODIFY
208#[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    /// Kinds of interactions allowed by a [`Var<T>`] in the current update.
220    ///
221    /// You can get the current capabilities of a var by using the [`AnyVar::capabilities`] method.
222    ///
223    /// [`Var<T>`]: crate::Var
224    /// [`AnyVar::capabilities`]: crate::AnyVar::capabilities
225    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
226    pub struct VarCapability: u8 {
227        /// Variable value can change.
228        ///
229        /// If this is set the [`AnyVar::is_new`] can be `true` in some updates, a variable can `NEW`
230        /// even if it cannot `MODIFY`, in this case the variable is a read-only wrapper on a read-write variable.
231        ///
232        /// [`AnyVar::is_new`]: crate::AnyVar::is_new
233        const NEW = 0b0000_0010;
234
235        /// Variable can be modified.
236        ///
237        /// If this is set [`Var::try_modify`] always returns `Ok`, if this is set `NEW` is also set.
238        ///
239        /// Note that modify requests from inside overridden animations can still be ignored, see [`AnyVar::modify_importance`].
240        ///
241        /// [`AnyVar::modify_importance`]: crate::AnyVar::modify_importance
242        /// [`Var::try_modify`]: crate::Var::try_modify
243        const MODIFY = 0b0000_0011;
244
245        /// Var represents different inner variables depending on the context it is used.
246        const CONTEXT = 0b1000_0000;
247
248        /// Variable capabilities can change to sometimes have the `MODIFY` capability.
249        const MODIFY_CHANGES = 0b0100_0000;
250        /// Variable capabilities can change to sometimes have the `CONTEXT` capability.
251        const CONTEXT_CHANGES = 0b0010_0000;
252
253        /// Var is an *arc* reference to the value and variable state, cloning the variable only clones a
254        /// reference to the variable, all references modify and notify the same state.
255        const SHARE = 0b0001_0000;
256    }
257}
258impl VarCapability {
259    /// If cannot `NEW` and is not `MODIFY_CHANGES`.
260    pub fn is_const(self) -> bool {
261        self.is_empty()
262    }
263
264    /// If does not have `MODIFY` capability and is not `MODIFY_CHANGES`.
265    pub fn is_always_read_only(&self) -> bool {
266        !self.contains(Self::MODIFY) && !self.contains(Self::MODIFY_CHANGES)
267    }
268
269    /// If does not have `MODIFY` capability.
270    pub fn is_read_only(self) -> bool {
271        !self.can_modify()
272    }
273
274    /// Has the `MODIFY` capability.
275    pub fn can_modify(self) -> bool {
276        self.contains(Self::MODIFY)
277    }
278
279    /// Has the `CONTEXT` capability.
280    pub fn is_contextual(self) -> bool {
281        self.contains(Self::CONTEXT)
282    }
283
284    /// Has the `CONTEXT` capability and does not have `CONTEXT_CHANGES`.
285    pub fn is_always_contextual(self) -> bool {
286        self.contains(Self::CONTEXT) && !self.contains(Self::CONTEXT_CHANGES)
287    }
288
289    /// Has the `SHARE` capability.
290    pub fn is_share(&self) -> bool {
291        self.contains(Self::SHARE)
292    }
293
294    /// Does not have the `SHARE` capability.
295    ///
296    /// Cloning this variable clones the value.
297    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        // can be new, but not modify
306        out.remove(Self::MODIFY & !Self::NEW);
307        // never will allow modify
308        out.remove(Self::MODIFY_CHANGES);
309
310        out
311    }
312}
313
314bitflags! {
315    #[derive(Clone, Copy)]
316    pub(crate) struct VarModifyUpdate: u8 {
317        /// Value was deref_mut or update was called
318        const UPDATE = 0b001;
319        /// Method update was called
320        const REQUESTED = 0b011;
321        /// Value was deref_mut
322        const TOUCHED = 0b101;
323    }
324}
325
326/// Mutable reference to a variable value.
327///
328/// The variable will notify an update only on `deref_mut`.
329pub 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    /// Replace the value if not equal.
337    ///
338    /// Note that you can also deref_mut to modify the value.
339    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    /// Notify an update, even if the value does not actually change.
359    pub fn update(&mut self) {
360        self.update |= VarModifyUpdate::REQUESTED;
361    }
362
363    /// Custom tags that will be shared with the var hooks if the value updates.
364    ///
365    /// The tags where set by previous modify closures or this one during this update cycle, so
366    /// tags can also be used to communicate between modify closures.
367    pub fn tags(&self) -> &[BoxAnyVarValue] {
368        &self.tags
369    }
370
371    /// Add a custom tag object that will be shared with the var hooks if the value updates.
372    pub fn push_tag(&mut self, tag: impl AnyVarValue) {
373        self.tags.push(BoxAnyVarValue::new(tag));
374    }
375
376    /// Sets a custom [`AnyVar::modify_importance`] value.
377    ///
378    /// Note that the modify info is already automatically set, using a custom value here
379    /// can easily break all future modify requests for this variable. The importance is set even if the
380    /// variable does not update (no actual value change or update request).
381    ///
382    /// [`AnyVar::modify_importance`]: crate::AnyVar::modify_importance
383    pub fn set_modify_importance(&mut self, importance: usize) {
384        self.custom_importance = Some(importance);
385    }
386
387    /// Strongly typed reference, if it is of the same type.
388    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    /// Immutable reference to the value.
400    ///
401    /// Note that you can also simply deref to the value.
402    pub fn value(&self) -> &dyn AnyVarValue {
403        &**self
404    }
405
406    /// Mutable reference to the value.
407    ///
408    /// Getting a mutable reference to the value flags the variable to notify update.
409    ///
410    /// Note that you can also simply deref to the value.
411    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
429/// Mutable reference to a variable value.
430///
431/// The variable will notify an update only on `deref_mut`.
432pub 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    /// Replace the value if not equal.
438    ///
439    /// Note that you can also deref_mut to modify the value.
440    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    /// Notify an update, even if the value does not actually change.
451    pub fn update(&mut self) {
452        self.inner.update();
453    }
454
455    /// Custom tags that will be shared with the var hooks if the value updates.
456    ///
457    /// The tags where set by previous modify closures or this one during this update cycle, so
458    /// tags can also be used to communicate between modify closures.
459    pub fn tags(&self) -> &[BoxAnyVarValue] {
460        self.inner.tags()
461    }
462
463    /// Add a custom tag object that will be shared with the var hooks if the value updates.
464    pub fn push_tag(&mut self, tag: impl AnyVarValue) {
465        self.inner.push_tag(tag);
466    }
467
468    /// Sets a custom [`AnyVar::modify_importance`] value.
469    ///
470    /// Note that the modify info is already automatically set, using a custom value here
471    /// can easily break all future modify requests for this variable. The importance is set even if the
472    /// variable does not update (no actual value change or update request).
473    ///
474    /// [`AnyVar::modify_importance`]: crate::AnyVar::modify_importance
475    pub fn set_modify_importance(&mut self, importance: usize) {
476        self.inner.set_modify_importance(importance);
477    }
478
479    /// Type erased reference.
480    pub fn as_any(&mut self) -> &mut AnyVarModify<'a> {
481        self.inner
482    }
483
484    /// Immutable reference to the value.
485    ///
486    /// Note that you can also simply deref to the value.
487    pub fn value(&self) -> &T {
488        self
489    }
490
491    /// Mutable reference to the value.
492    ///
493    /// Getting a mutable reference to the value flags the variable to notify update.
494    ///
495    /// Note that you can also simply deref to the value.
496    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/// Handle to a variable or animation hook.
514///
515/// This can represent a widget subscriber, a var binding, var app handler or animation, dropping the handler stops
516/// the behavior it represents.
517///
518/// Note that the hook closure is not dropped immediately when the handle is dropped, usually it will drop only the next
519/// time it would have been called.
520#[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    /// Handle to no variable.
545    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    /// Returns `true` if the handle is a [`dummy`].
555    ///
556    /// [`dummy`]: VarHandle::dummy
557    pub fn is_dummy(&self) -> bool {
558        self.0.is_none()
559    }
560
561    /// Drop the handle without stopping the behavior it represents.
562    ///
563    /// Note that the behavior can still be stopped by dropping the involved variables.
564    pub fn perm(self) {
565        if let Some(c) = &self.0 {
566            c.store(true, std::sync::atomic::Ordering::Relaxed);
567        }
568    }
569
570    /// Create a [`VarHandles`] collection with `self` and `other`.
571    pub fn chain(self, other: Self) -> VarHandles {
572        VarHandles(smallvec::smallvec![self, other])
573    }
574
575    /// Create a weak reference to this handle.
576    ///
577    /// Note that weak references to dummy handles cannot upgrade back.
578    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/// Weak reference to a [`VarHandle`].
587#[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    /// Upgrade to strong handle.
602    ///
603    /// Returns `None` if no strong reference to the handle remains.
604    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    /// New dummy weak reference that does not upgrade.
610    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/// Represents a collection of var handles.
633#[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    /// Empty collection.
638    pub const fn dummy() -> Self {
639        VarHandles(smallvec::SmallVec::new_const())
640    }
641
642    /// Returns `true` if empty or all handles are dummy.
643    pub fn is_dummy(&self) -> bool {
644        self.0.is_empty() || self.0.iter().all(VarHandle::is_dummy)
645    }
646
647    /// Drop all handles without stopping their behavior.
648    pub fn perm(self) {
649        for handle in self.0 {
650            handle.perm()
651        }
652    }
653
654    /// Add the `other` handle to the collection, if it is not dummy.
655    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    /// Drop all handles.
663    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}