Skip to main content

appcui/system/
handle.rs

1use std::{
2    marker::PhantomData,
3    sync::atomic::{AtomicUsize, Ordering},
4};
5
6static GLOBAL_ID: AtomicUsize = AtomicUsize::new(0);
7
8pub(crate) trait HandleSupport<T> {
9    fn handle(&self) -> Handle<T>;
10    fn set_handle(&mut self, handle: Handle<T>);
11}
12
13/// The `Handle<T>` generic type provides a type-safe way to reference and manage UI components:
14/// - Type-safe references to UI controls, menus, and other components
15/// - Unique identification of components across the application
16/// - Safe component lifecycle management
17/// - Support for component hierarchy and relationships
18/// - Thread-safe component access  
19pub struct Handle<T> {
20    value: u64,
21    _phantom: PhantomData<T>,
22}
23impl<T> Handle<T> {
24    /// The `None` handle value
25    #[allow(non_upper_case_globals)]
26    pub const None: Handle<T> = Handle {
27        value: u64::MAX,
28        _phantom: PhantomData,
29    };
30    pub(crate) fn with_id(id: u32, index: u32) -> Self {
31        Self {
32            value: (index as u64) | ((id as u64) << 32),
33            _phantom: PhantomData,
34        }
35    }
36    pub(crate) fn new(index: u32) -> Self {
37        let id = ((GLOBAL_ID.fetch_add(1, Ordering::SeqCst) as u32) % 0xFFFF_FFFE) as u64;
38        Self {
39            value: (index as u64) | (id << 32),
40            _phantom: PhantomData,
41        }
42    }
43    #[inline(always)]
44    pub(crate) fn index(&self) -> usize {
45        (self.value & 0xFFFFFFFF) as usize
46    }
47    #[inline(always)]
48    pub(crate) fn cast<U>(&self) -> Handle<U> {
49        let r: Handle<U> = Handle {
50            value: self.value,
51            _phantom: PhantomData,
52        };
53        r
54    }
55    /// # Safety
56    ///
57    /// This function should not be used (its purpose is to serve some proc-macros such as **#\[CustomControl\])** to convert a handle. Using this will imply an unsafe block and the results can be undetermined.
58    #[inline(always)]
59    pub unsafe fn unsafe_cast<U>(&self) -> Handle<U> {
60        let r: Handle<U> = Handle {
61            value: self.value,
62            _phantom: PhantomData,
63        };
64        r
65    }
66    /// Checks if the handle is `None`
67    #[inline(always)]
68    pub fn is_none(&self) -> bool {
69        self.value == u64::MAX
70    }
71}
72impl<T> Clone for Handle<T> {
73    fn clone(&self) -> Self {
74        *self
75    }
76}
77impl<T> Copy for Handle<T> {}
78impl<T, U> PartialEq<Handle<T>> for Handle<U> {
79    fn eq(&self, other: &Handle<T>) -> bool {
80        self.value == other.value
81    }
82}
83impl<T> Default for Handle<T> {
84    fn default() -> Self {
85        Handle {
86            value: u64::MAX,
87            _phantom: PhantomData,
88        }
89    }
90}
91impl<T> std::fmt::Debug for Handle<T> {
92    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
93        write!(f, "Handle {{ index: {}, id: {} }}", self.index(), (self.value >> 32) & 0xFFFFFFFF)
94    }
95}