use std::cmp::Ordering;
use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::u32;
pub const MAXIMUM_CAPACITY: usize = u32::MAX as usize - 1;
pub type IdTag = u32;
pub type IdIndex = u32;
pub struct Id<T> {
#[doc(hidden)]
pub index: IdIndex,
#[doc(hidden)]
pub tag: IdTag,
#[doc(hidden)]
pub _data: PhantomData<T>,
}
impl<T> Id<T> {
pub fn invalid() -> Self {
Id {
index: u32::MAX,
tag: u32::MAX,
_data: PhantomData,
}
}
pub fn cast<U>(self) -> Id<U> {
Id {
index: self.index,
tag: self.tag,
_data: PhantomData,
}
}
}
impl<T> Debug for Id<T> {
fn fmt(&self, formatter: &mut Formatter) -> FmtResult {
write!(formatter, "{}.{:x}", self.index, self.tag)
}
}
impl<T> Hash for Id<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
(self.index, self.tag).hash(state)
}
}
impl<T> PartialOrd for Id<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T> PartialEq for Id<T> {
fn eq(&self, other: &Self) -> bool {
self.tag == other.tag && self.index == other.index
}
}
impl<T> Ord for Id<T> {
fn cmp(&self, other: &Self) -> Ordering {
(self.tag, self.index).cmp(&(other.tag, other.index))
}
}
#[cfg_attr(feature = "cargo-clippy", allow(expl_impl_clone_on_copy))]
impl<T> Clone for Id<T> {
fn clone(&self) -> Self {
Id {
index: self.index,
tag: self.tag,
_data: PhantomData,
}
}
}
impl<T> Copy for Id<T> {}
impl<T> Eq for Id<T> {}
impl<T> Default for Id<T> {
fn default() -> Self {
Self::invalid()
}
}