use std::num::NonZeroU64;
#[derive(Clone, Copy, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Id(NonZeroU64);
impl nohash_hasher::IsEnabled for Id {}
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 as _, Hasher as _};
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);
}
pub type IdSet = nohash_hasher::IntSet<Id>;
pub type IdMap<V> = nohash_hasher::IntMap<Id, V>;