1use std::num::NonZeroU64;
4
5#[derive(Clone, Copy, Hash, Eq, PartialEq)]
33#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
34pub struct Id(NonZeroU64);
35
36impl Id {
37 pub const NULL: Self = Self(NonZeroU64::MAX);
43
44 #[inline]
45 const fn from_hash(hash: u64) -> Self {
46 if let Some(nonzero) = NonZeroU64::new(hash) {
47 Self(nonzero)
48 } else {
49 Self(NonZeroU64::MIN) }
51 }
52
53 pub fn new(source: impl std::hash::Hash) -> Self {
55 Self::from_hash(ahash::RandomState::with_seeds(1, 2, 3, 4).hash_one(source))
56 }
57
58 pub fn with(self, child: impl std::hash::Hash) -> Self {
60 use std::hash::{BuildHasher, Hasher};
61 let mut hasher = ahash::RandomState::with_seeds(1, 2, 3, 4).build_hasher();
62 hasher.write_u64(self.0.get());
63 child.hash(&mut hasher);
64 Self::from_hash(hasher.finish())
65 }
66
67 pub fn short_debug_format(&self) -> String {
69 format!("{:04X}", self.value() as u16)
70 }
71
72 #[inline(always)]
76 pub fn value(&self) -> u64 {
77 self.0.get()
78 }
79
80 #[cfg(feature = "accesskit")]
81 pub(crate) fn accesskit_id(&self) -> accesskit::NodeId {
82 self.value().into()
83 }
84}
85
86impl std::fmt::Debug for Id {
87 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88 write!(f, "{:04X}", self.value() as u16)
89 }
90}
91
92impl From<&'static str> for Id {
94 #[inline]
95 fn from(string: &'static str) -> Self {
96 Self::new(string)
97 }
98}
99
100impl From<String> for Id {
101 #[inline]
102 fn from(string: String) -> Self {
103 Self::new(string)
104 }
105}
106
107#[test]
108fn id_size() {
109 assert_eq!(std::mem::size_of::<Id>(), 8);
110 assert_eq!(std::mem::size_of::<Option<Id>>(), 8);
111}
112
113#[derive(Default)]
117pub struct IdHasher(u64);
118
119impl std::hash::Hasher for IdHasher {
120 fn write(&mut self, _: &[u8]) {
121 unreachable!("Invalid use of IdHasher");
122 }
123
124 fn write_u8(&mut self, _n: u8) {
125 unreachable!("Invalid use of IdHasher");
126 }
127
128 fn write_u16(&mut self, _n: u16) {
129 unreachable!("Invalid use of IdHasher");
130 }
131
132 fn write_u32(&mut self, _n: u32) {
133 unreachable!("Invalid use of IdHasher");
134 }
135
136 #[inline(always)]
137 fn write_u64(&mut self, n: u64) {
138 self.0 = n;
139 }
140
141 fn write_usize(&mut self, _n: usize) {
142 unreachable!("Invalid use of IdHasher");
143 }
144
145 fn write_i8(&mut self, _n: i8) {
146 unreachable!("Invalid use of IdHasher");
147 }
148
149 fn write_i16(&mut self, _n: i16) {
150 unreachable!("Invalid use of IdHasher");
151 }
152
153 fn write_i32(&mut self, _n: i32) {
154 unreachable!("Invalid use of IdHasher");
155 }
156
157 fn write_i64(&mut self, _n: i64) {
158 unreachable!("Invalid use of IdHasher");
159 }
160
161 fn write_isize(&mut self, _n: isize) {
162 unreachable!("Invalid use of IdHasher");
163 }
164
165 #[inline(always)]
166 fn finish(&self) -> u64 {
167 self.0
168 }
169}
170
171#[derive(Copy, Clone, Debug, Default)]
172#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
173pub struct BuildIdHasher {}
174
175impl std::hash::BuildHasher for BuildIdHasher {
176 type Hasher = IdHasher;
177
178 #[inline(always)]
179 fn build_hasher(&self) -> IdHasher {
180 IdHasher::default()
181 }
182}
183
184pub type IdSet = std::collections::HashSet<Id, BuildIdHasher>;
186
187pub type IdMap<V> = std::collections::HashMap<Id, V, BuildIdHasher>;