layer_shika_domain/value_objects/
handle.rs

1use std::fmt::{Debug, Formatter, Result as FmtResult};
2use std::hash::Hash;
3use std::hash::Hasher;
4use std::marker::PhantomData;
5use std::sync::atomic::{AtomicUsize, Ordering};
6
7static NEXT_HANDLE_ID: AtomicUsize = AtomicUsize::new(1);
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct HandleId(usize);
11
12impl HandleId {
13    fn new() -> Self {
14        Self(NEXT_HANDLE_ID.fetch_add(1, Ordering::Relaxed))
15    }
16
17    const fn from_raw(id: usize) -> Self {
18        Self(id)
19    }
20
21    pub const fn as_usize(&self) -> usize {
22        self.0
23    }
24}
25
26impl Hash for HandleId {
27    fn hash<H: Hasher>(&self, state: &mut H) {
28        self.0.hash(state);
29    }
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub struct Output;
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub struct Popup;
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub struct Surface;
40
41/// Type-safe unique identifier for runtime resources
42///
43/// Used as `OutputHandle`, `PopupHandle`, or `SurfaceHandle` to identify
44/// specific instances of those resources.
45pub struct Handle<T> {
46    id: HandleId,
47    _marker: PhantomData<T>,
48}
49
50impl<T> Debug for Handle<T> {
51    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
52        f.debug_struct("Handle").field("id", &self.id).finish()
53    }
54}
55
56impl<T> Handle<T> {
57    #[must_use]
58    pub fn new() -> Self {
59        Self {
60            id: HandleId::new(),
61            _marker: PhantomData,
62        }
63    }
64
65    #[must_use]
66    pub const fn from_raw(id: usize) -> Self {
67        Self {
68            id: HandleId::from_raw(id),
69            _marker: PhantomData,
70        }
71    }
72
73    #[must_use]
74    pub const fn id(&self) -> usize {
75        self.id.as_usize()
76    }
77}
78
79impl<T> Default for Handle<T> {
80    fn default() -> Self {
81        Self::new()
82    }
83}
84
85#[allow(clippy::non_canonical_clone_impl)]
86impl<T> Clone for Handle<T> {
87    fn clone(&self) -> Self {
88        Self {
89            id: self.id,
90            _marker: PhantomData,
91        }
92    }
93}
94
95impl<T> Copy for Handle<T> {}
96
97impl<T> PartialEq for Handle<T> {
98    fn eq(&self, other: &Self) -> bool {
99        self.id == other.id
100    }
101}
102
103impl<T> Eq for Handle<T> {}
104
105impl<T> Hash for Handle<T> {
106    fn hash<H: Hasher>(&self, state: &mut H) {
107        self.id.hash(state);
108    }
109}
110
111impl Handle<Popup> {
112    #[must_use]
113    pub const fn key(self) -> usize {
114        self.id()
115    }
116}
117
118/// Unique identifier for an output (monitor)
119pub type OutputHandle = Handle<Output>;
120/// Unique identifier for a popup window
121pub type PopupHandle = Handle<Popup>;
122/// Unique identifier for a layer surface
123pub type SurfaceHandle = Handle<Surface>;