agui_core/
reference.rs

1use std::{
2    fmt::Debug,
3    sync::{Arc, Weak},
4};
5
6/// Holds a reference that is either `None`, `Owned`, or `Borrowed`.
7///
8/// It's used to give a single field that can accept `Option` (without additional wrapping),
9/// an owned value, or a reference to an owned value (to prevent unnecessary clones).
10///
11/// # Example
12///
13/// ```
14/// pub struct Button {
15///     // Allows the Button to provide its own default, accept an owned value from a parent
16///     // widget, or a reference to a layout.
17///     pub layout: Ref<Layout>,
18/// }
19/// ```
20pub enum Ref<V>
21where
22    V: ?Sized,
23{
24    /// No value.
25    None,
26
27    /// Owned data.
28    Owned(Arc<V>),
29
30    /// Borrowed data. Unlike Owned, this is not guaranteed to exist, as it only
31    /// holds a weak reference to the Owned value. It should never be expected for the value
32    /// to exist.
33    Borrowed(Weak<V>),
34}
35
36impl<V> Default for Ref<V> {
37    fn default() -> Self {
38        Self::None
39    }
40}
41
42impl<V> Debug for Ref<V>
43where
44    V: Debug,
45{
46    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47        match self {
48            Self::None => write!(f, "None"),
49            Self::Owned(value) => Debug::fmt(&value, f),
50            Self::Borrowed(value) => match value.upgrade() {
51                Some(value) => Debug::fmt(&value, f),
52                None => write!(f, "Gone"),
53            },
54        }
55    }
56}
57
58impl<V> Ref<V> {
59    /// Creates an Owned reference to `value`.
60    #[must_use]
61    pub fn new(value: V) -> Self {
62        Self::Owned(Arc::new(value))
63    }
64
65    /// Returns true if this reference points to a value in memory.
66    ///
67    /// Will always be `true` if the Ref is `Owned`, will always be `None` if the Ref is `None`,
68    /// but if it's `Borrowed`, it will only return `true` if the borrowed value is still in memory.
69    #[must_use]
70    pub fn is_valid(&self) -> bool {
71        match self {
72            Self::None => false,
73            Self::Owned(_) => true,
74            Self::Borrowed(weak) => weak.strong_count() > 0,
75        }
76    }
77
78    /// Attempst to fetch the value that this reference is wrapping.
79    #[must_use]
80    pub fn try_get(&self) -> Option<Arc<V>> {
81        match self {
82            Self::None => None,
83            Self::Owned(value) => Some(Arc::clone(value)),
84            Self::Borrowed(weak) => weak.upgrade(),
85        }
86    }
87
88    /// Fetch the underlying value that this reference is wrapping.
89    ///
90    /// # Panics
91    ///
92    /// Will panic if the value no longer exists, or the reference is empty.
93    #[must_use]
94    pub fn get(&self) -> Arc<V> {
95        match self {
96            Self::None => panic!("layout ref points to nothing"),
97            Self::Owned(value) => Arc::clone(value),
98            Self::Borrowed(weak) => match weak.upgrade() {
99                Some(value) => value,
100                None => panic!("value no longer exists"),
101            },
102        }
103    }
104}
105
106impl<V> Clone for Ref<V> {
107    fn clone(&self) -> Self {
108        match self {
109            Self::None => Self::None,
110            Self::Owned(value) => Self::Borrowed(Arc::downgrade(value)),
111            Self::Borrowed(value) => Self::Borrowed(Weak::clone(value)),
112        }
113    }
114}
115
116impl<T> From<T> for Ref<T> {
117    fn from(val: T) -> Self {
118        Self::Owned(Arc::new(val))
119    }
120}