Skip to main content

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 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/// Error when an attempt to modify a variable without the [`MODIFY`] capability is made.
197///
198/// [`MODIFY`]: VarCapability::MODIFY
199#[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    /// Kinds of interactions allowed by a [`Var<T>`] in the current update.
211    ///
212    /// You can get the current capabilities of a var by using the [`AnyVar::capabilities`] method.
213    ///
214    /// [`Var<T>`]: crate::Var
215    /// [`AnyVar::capabilities`]: crate::AnyVar::capabilities
216    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
217    pub struct VarCapability: u8 {
218        /// Variable value can change.
219        ///
220        /// If this is set the [`AnyVar::is_new`] can be `true` in some updates, a variable can `NEW`
221        /// even if it cannot `MODIFY`, in this case the variable is a read-only wrapper on a read-write variable.
222        ///
223        /// [`AnyVar::is_new`]: crate::AnyVar::is_new
224        const NEW = 0b0000_0010;
225
226        /// Variable can be modified.
227        ///
228        /// If this is set [`Var::try_modify`] always returns `Ok`, if this is set `NEW` is also set.
229        ///
230        /// Note that modify requests from inside overridden animations can still be ignored, see [`AnyVar::modify_importance`].
231        ///
232        /// [`AnyVar::modify_importance`]: crate::AnyVar::modify_importance
233        /// [`Var::try_modify`]: crate::Var::try_modify
234        const MODIFY = 0b0000_0011;
235
236        /// Var represents different inner variables depending on the context it is used.
237        const CONTEXT = 0b1000_0000;
238
239        /// Variable capabilities can change to sometimes have the `MODIFY` capability.
240        const MODIFY_CHANGES = 0b0100_0000;
241        /// Variable capabilities can change to sometimes have the `CONTEXT` capability.
242        const CONTEXT_CHANGES = 0b0010_0000;
243
244        /// Var is an *arc* reference to the value and variable state, cloning the variable only clones a
245        /// reference to the variable, all references modify and notify the same state.
246        const SHARE = 0b0001_0000;
247    }
248}
249impl VarCapability {
250    /// If cannot `NEW` and is not `MODIFY_CHANGES`.
251    pub fn is_const(self) -> bool {
252        self.is_empty()
253    }
254
255    /// If does not have `MODIFY` capability and is not `MODIFY_CHANGES`.
256    pub fn is_always_read_only(&self) -> bool {
257        !self.contains(Self::MODIFY) && !self.contains(Self::MODIFY_CHANGES)
258    }
259
260    /// If does not have `MODIFY` capability.
261    pub fn is_read_only(self) -> bool {
262        !self.can_modify()
263    }
264
265    /// Has the `MODIFY` capability.
266    pub fn can_modify(self) -> bool {
267        self.contains(Self::MODIFY)
268    }
269
270    /// Has the `CONTEXT` capability.
271    pub fn is_contextual(self) -> bool {
272        self.contains(Self::CONTEXT)
273    }
274
275    /// Has the `CONTEXT` capability and does not have `CONTEXT_CHANGES`.
276    pub fn is_always_contextual(self) -> bool {
277        self.contains(Self::CONTEXT) && !self.contains(Self::CONTEXT_CHANGES)
278    }
279
280    /// Has the `SHARE` capability.
281    pub fn is_share(&self) -> bool {
282        self.contains(Self::SHARE)
283    }
284
285    /// Does not have the `SHARE` capability.
286    ///
287    /// Cloning this variable clones the value.
288    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        // can be new, but not modify
297        out.remove(Self::MODIFY & !Self::NEW);
298        // never will allow modify
299        out.remove(Self::MODIFY_CHANGES);
300
301        out
302    }
303}
304
305bitflags! {
306    #[derive(Clone, Copy)]
307    pub(crate) struct VarModifyUpdate: u8 {
308        /// Value was deref_mut or update was called
309        const UPDATE = 0b001;
310        /// Method update was called
311        const REQUESTED = 0b011;
312        /// Value was deref_mut
313        const TOUCHED = 0b101;
314    }
315}
316
317/// Mutable reference to a variable value.
318///
319/// The variable will notify an update only on `deref_mut`.
320pub 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    /// Replace the value if not equal.
328    ///
329    /// Note that you can also deref_mut to modify the value.
330    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    /// Notify an update, even if the value does not actually change.
350    pub fn update(&mut self) {
351        self.update |= VarModifyUpdate::REQUESTED;
352    }
353
354    /// Custom tags that will be shared with the var hooks if the value updates.
355    ///
356    /// The tags where set by previous modify closures or this one during this update cycle, so
357    /// tags can also be used to communicate between modify closures.
358    pub fn tags(&self) -> &[BoxAnyVarValue] {
359        &self.tags
360    }
361
362    /// Add a custom tag object that will be shared with the var hooks if the value updates.
363    pub fn push_tag(&mut self, tag: impl AnyVarValue) {
364        self.tags.push(BoxAnyVarValue::new(tag));
365    }
366
367    /// Sets a custom [`AnyVar::modify_importance`] value.
368    ///
369    /// Note that the modify info is already automatically set, using a custom value here
370    /// can easily break all future modify requests for this variable. The importance is set even if the
371    /// variable does not update (no actual value change or update request).
372    ///
373    /// [`AnyVar::modify_importance`]: crate::AnyVar::modify_importance
374    pub fn set_modify_importance(&mut self, importance: usize) {
375        self.custom_importance = Some(importance);
376    }
377
378    /// Strongly typed reference, if it is of the same type.
379    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    /// Immutable reference to the value.
391    ///
392    /// Note that you can also simply deref to the value.
393    pub fn value(&self) -> &dyn AnyVarValue {
394        &**self
395    }
396
397    /// Mutable reference to the value.
398    ///
399    /// Getting a mutable reference to the value flags the variable to notify update.
400    ///
401    /// Note that you can also simply deref to the value.
402    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
420/// Mutable reference to a variable value.
421///
422/// The variable will notify an update only on `deref_mut`.
423pub 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    /// Replace the value if not equal.
429    ///
430    /// Note that you can also deref_mut to modify the value.
431    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    /// Notify an update, even if the value does not actually change.
442    pub fn update(&mut self) {
443        self.inner.update();
444    }
445
446    /// Custom tags that will be shared with the var hooks if the value updates.
447    ///
448    /// The tags where set by previous modify closures or this one during this update cycle, so
449    /// tags can also be used to communicate between modify closures.
450    pub fn tags(&self) -> &[BoxAnyVarValue] {
451        self.inner.tags()
452    }
453
454    /// Add a custom tag object that will be shared with the var hooks if the value updates.
455    pub fn push_tag(&mut self, tag: impl AnyVarValue) {
456        self.inner.push_tag(tag);
457    }
458
459    /// Sets a custom [`AnyVar::modify_importance`] value.
460    ///
461    /// Note that the modify info is already automatically set, using a custom value here
462    /// can easily break all future modify requests for this variable. The importance is set even if the
463    /// variable does not update (no actual value change or update request).
464    ///
465    /// [`AnyVar::modify_importance`]: crate::AnyVar::modify_importance
466    pub fn set_modify_importance(&mut self, importance: usize) {
467        self.inner.set_modify_importance(importance);
468    }
469
470    /// Type erased reference.
471    pub fn as_any(&mut self) -> &mut AnyVarModify<'a> {
472        self.inner
473    }
474
475    /// Immutable reference to the value.
476    ///
477    /// Note that you can also simply deref to the value.
478    pub fn value(&self) -> &T {
479        self
480    }
481
482    /// Mutable reference to the value.
483    ///
484    /// Getting a mutable reference to the value flags the variable to notify update.
485    ///
486    /// Note that you can also simply deref to the value.
487    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/// Handle to a variable or animation hook.
505///
506/// This can represent a widget subscriber, a var binding, var app handler or animation, dropping the handler stops
507/// the behavior it represents.
508///
509/// Note that the hook closure is not dropped immediately when the handle is dropped, usually it will drop only the next
510/// time it would have been called.
511#[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    /// Handle to no variable.
536    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    /// Returns `true` if the handle is a [`dummy`].
546    ///
547    /// [`dummy`]: VarHandle::dummy
548    pub fn is_dummy(&self) -> bool {
549        self.0.is_none()
550    }
551
552    /// Drop the handle without stopping the behavior it represents.
553    ///
554    /// Note that the behavior can still be stopped by dropping the involved variables.
555    pub fn perm(self) {
556        if let Some(c) = &self.0 {
557            c.store(true, std::sync::atomic::Ordering::Relaxed);
558        }
559    }
560
561    /// Create a [`VarHandles`] collection with `self` and `other`.
562    pub fn chain(self, other: Self) -> VarHandles {
563        VarHandles(smallvec::smallvec![self, other])
564    }
565
566    /// Create a weak reference to this handle.
567    ///
568    /// Note that weak references to dummy handles cannot upgrade back.
569    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/// Weak reference to a [`VarHandle`].
578#[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    /// Upgrade to strong handle.
593    ///
594    /// Returns `None` if no strong reference to the handle remains.
595    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    /// New dummy weak reference that does not upgrade.
601    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/// Represents a collection of var handles.
624#[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    /// Empty collection.
629    pub const fn dummy() -> Self {
630        VarHandles(smallvec::SmallVec::new_const())
631    }
632
633    /// Returns `true` if empty or all handles are dummy.
634    pub fn is_dummy(&self) -> bool {
635        self.0.is_empty() || self.0.iter().all(VarHandle::is_dummy)
636    }
637
638    /// Drop all handles without stopping their behavior.
639    pub fn perm(self) {
640        for handle in self.0 {
641            handle.perm()
642        }
643    }
644
645    /// Add the `other` handle to the collection, if it is not dummy.
646    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    /// Drop all handles.
654    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}