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
13pub struct Handle<T> {
20 value: u64,
21 _phantom: PhantomData<T>,
22}
23impl<T> Handle<T> {
24 #[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 #[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 #[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}