layer_shika_domain/value_objects/
handle.rs1use 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
41pub 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
118pub type OutputHandle = Handle<Output>;
120pub type PopupHandle = Handle<Popup>;
122pub type SurfaceHandle = Handle<Surface>;