use std::num::NonZeroU64;
#[derive(Clone, Copy, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Id(NonZeroU64);
impl Id {
pub const NULL: Self = Self(NonZeroU64::MAX);
#[inline]
const fn from_hash(hash: u64) -> Self {
if let Some(nonzero) = NonZeroU64::new(hash) {
Self(nonzero)
} else {
Self(NonZeroU64::MIN) }
}
pub fn new(source: impl std::hash::Hash) -> Self {
Self::from_hash(ahash::RandomState::with_seeds(1, 2, 3, 4).hash_one(source))
}
pub fn with(self, child: impl std::hash::Hash) -> Self {
use std::hash::{BuildHasher, Hasher};
let mut hasher = ahash::RandomState::with_seeds(1, 2, 3, 4).build_hasher();
hasher.write_u64(self.0.get());
child.hash(&mut hasher);
Self::from_hash(hasher.finish())
}
pub fn short_debug_format(&self) -> String {
format!("{:04X}", self.value() as u16)
}
#[inline(always)]
pub fn value(&self) -> u64 {
self.0.get()
}
#[cfg(feature = "accesskit")]
pub(crate) fn accesskit_id(&self) -> accesskit::NodeId {
self.value().into()
}
}
impl std::fmt::Debug for Id {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:04X}", self.value() as u16)
}
}
impl From<&'static str> for Id {
#[inline]
fn from(string: &'static str) -> Self {
Self::new(string)
}
}
impl From<String> for Id {
#[inline]
fn from(string: String) -> Self {
Self::new(string)
}
}
#[test]
fn id_size() {
assert_eq!(std::mem::size_of::<Id>(), 8);
assert_eq!(std::mem::size_of::<Option<Id>>(), 8);
}
#[derive(Default)]
pub struct IdHasher(u64);
impl std::hash::Hasher for IdHasher {
fn write(&mut self, _: &[u8]) {
unreachable!("Invalid use of IdHasher");
}
fn write_u8(&mut self, _n: u8) {
unreachable!("Invalid use of IdHasher");
}
fn write_u16(&mut self, _n: u16) {
unreachable!("Invalid use of IdHasher");
}
fn write_u32(&mut self, _n: u32) {
unreachable!("Invalid use of IdHasher");
}
#[inline(always)]
fn write_u64(&mut self, n: u64) {
self.0 = n;
}
fn write_usize(&mut self, _n: usize) {
unreachable!("Invalid use of IdHasher");
}
fn write_i8(&mut self, _n: i8) {
unreachable!("Invalid use of IdHasher");
}
fn write_i16(&mut self, _n: i16) {
unreachable!("Invalid use of IdHasher");
}
fn write_i32(&mut self, _n: i32) {
unreachable!("Invalid use of IdHasher");
}
fn write_i64(&mut self, _n: i64) {
unreachable!("Invalid use of IdHasher");
}
fn write_isize(&mut self, _n: isize) {
unreachable!("Invalid use of IdHasher");
}
#[inline(always)]
fn finish(&self) -> u64 {
self.0
}
}
#[derive(Copy, Clone, Debug, Default)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct BuildIdHasher {}
impl std::hash::BuildHasher for BuildIdHasher {
type Hasher = IdHasher;
#[inline(always)]
fn build_hasher(&self) -> IdHasher {
IdHasher::default()
}
}
pub type IdSet = std::collections::HashSet<Id, BuildIdHasher>;
pub type IdMap<V> = std::collections::HashMap<Id, V, BuildIdHasher>;