1#[cfg(feature = "serde")]
2mod serde;
3
4use core::{cmp::Ordering, marker::PhantomData, num::NonZeroU32};
5
6pub struct Id<T> {
8 data: NonZeroU32,
9 phantom: PhantomData<fn() -> T>,
10}
11
12impl<T> core::hash::Hash for Id<T> {
13 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
14 self.data.hash(state);
15 }
16}
17
18impl<T> Eq for Id<T> {}
19
20impl<T> PartialEq for Id<T> {
21 fn eq(&self, other: &Self) -> bool {
22 self.data == other.data
23 }
24}
25
26impl<T> PartialOrd for Id<T> {
27 fn partial_cmp(&self, other: &Id<T>) -> Option<Ordering> {
28 Some(self.cmp(other))
29 }
30}
31
32impl<T> Ord for Id<T> {
33 fn cmp(&self, other: &Id<T>) -> Ordering {
34 match self.index().cmp(&other.index()) {
35 ord @ Ordering::Less | ord @ Ordering::Greater => ord,
36 Ordering::Equal => self.gen().cmp(&other.gen()),
37 }
38 }
39}
40
41impl<T> core::fmt::Debug for Id<T> {
42 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
43 write!(f, "Id({}.{})", self.index(), self.gen())
44 }
45}
46
47impl<T> Clone for Id<T> {
48 fn clone(&self) -> Self {
49 *self
50 }
51}
52
53impl<T> Copy for Id<T> {}
54
55impl<T> Id<T> {
56 pub(crate) fn new(index: u32) -> Id<T> {
57 Id {
58 data: unsafe { NonZeroU32::new_unchecked(index + 1) },
59 phantom: PhantomData,
60 }
61 }
62
63 #[cfg(test)]
64 pub(crate) fn with_gen(index: u32, gen: u32) -> Id<T> {
65 Id {
66 data: unsafe { NonZeroU32::new_unchecked(index + 1 | (gen << 24)) },
67 phantom: PhantomData,
68 }
69 }
70
71 pub fn invalid() -> Self {
74 Id {
75 data: unsafe { NonZeroU32::new_unchecked(u32::MAX) },
76 phantom: PhantomData,
77 }
78 }
79
80 pub(crate) fn index(self) -> u32 {
81 (self.data.get() & !(255 << 24)) - 1
83 }
84
85 pub(crate) fn uindex(self) -> usize {
86 self.index() as usize
87 }
88
89 pub(crate) fn set_index(&mut self, new_index: u32) {
90 self.data = unsafe { NonZeroU32::new_unchecked((new_index + 1) | (self.gen() << 24)) };
91 }
92
93 pub(crate) fn gen(self) -> u32 {
94 self.data.get() >> 24
96 }
97
98 pub(crate) fn increment_gen(&mut self) {
99 self.data =
100 unsafe { NonZeroU32::new_unchecked((self.index() + 1) | ((self.gen() + 1) << 24)) };
101 }
102
103 pub fn untype(self) -> UntypedId {
105 UntypedId(Id {
106 data: self.data,
107 phantom: PhantomData,
108 })
109 }
110}
111
112#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
114pub struct UntypedId(Id<()>);
115
116impl core::fmt::Debug for UntypedId {
117 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
118 write!(f, "UntypedId({}.{})", self.0.index(), self.0.gen())
119 }
120}
121
122impl UntypedId {
123 pub fn as_type<T>(self) -> Id<T> {
125 Id {
126 data: self.0.data,
127 phantom: PhantomData,
128 }
129 }
130}