pub const ID_SIZE: usize = 32;
#[derive(Debug)]
#[repr(transparent)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(transparent)
)]
pub struct Id<T: ?Sized = ()>(
#[cfg_attr(feature = "serde", serde(with = "hex::serde"))] [u8; ID_SIZE],
std::marker::PhantomData<T>,
);
impl<T> Id<T> {
#[must_use]
pub fn cast<U>(self) -> Id<U> {
Id::<U>(self.0, std::marker::PhantomData)
}
}
#[cfg(feature = "rand")]
impl<T> rand::distr::Distribution<Id<T>> for rand::distr::StandardUniform {
fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> Id<T> {
use rand::RngExt;
Id(rng.random(), std::marker::PhantomData)
}
}
impl<T> Clone for Id<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for Id<T> {}
impl<T> PartialEq for Id<T> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<T> Eq for Id<T> {}
impl<T> PartialOrd for Id<T> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<T> Ord for Id<T> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.0.cmp(&other.0)
}
}
impl<T> std::hash::Hash for Id<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl<T> std::fmt::Display for Id<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
hex::encode(self.0).fmt(f)
}
}
impl<T> TryFrom<&str> for Id<T> {
type Error = hex::FromHexError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
value.parse() }
}
impl<T> TryFrom<String> for Id<T> {
type Error = hex::FromHexError;
fn try_from(value: String) -> Result<Self, Self::Error> {
value.parse()
}
}
impl<T> std::str::FromStr for Id<T> {
type Err = hex::FromHexError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
hex::FromHex::from_hex(s)
}
}
impl<T> hex::FromHex for Id<T> {
type Error = hex::FromHexError;
fn from_hex<T1: AsRef<[u8]>>(hex: T1) -> Result<Self, Self::Error> {
let id = <[u8; 32]>::from_hex(hex)?;
Ok(Self(id, std::marker::PhantomData))
}
}
impl<T> AsRef<[u8]> for Id<T> {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl<T> std::borrow::Borrow<[u8]> for Id<T> {
fn borrow(&self) -> &[u8] {
&self.0
}
}
impl<T> std::borrow::Borrow<[u8; 32]> for Id<T> {
fn borrow(&self) -> &[u8; 32] {
&self.0
}
}
impl<T> std::ops::Deref for Id<T> {
type Target = [u8; 32];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> From<[u8; 32]> for Id<T> {
fn from(value: [u8; 32]) -> Self {
Self(value, std::marker::PhantomData)
}
}
impl<T> From<Id<T>> for [u8; 32] {
fn from(value: Id<T>) -> Self {
value.0
}
}
impl<T> TryFrom<Vec<u8>> for Id<T> {
type Error = std::array::TryFromSliceError;
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
Self::try_from(&*value)
}
}
impl<T> TryFrom<&[u8]> for Id<T> {
type Error = std::array::TryFromSliceError;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
let value: [u8; 32] = value.try_into()?;
Ok(Self(value, std::marker::PhantomData))
}
}
#[derive(Debug, Clone, Copy)]
pub struct Entry<T> {
entry: T,
id: Id<T>,
}
impl<T> std::ops::Deref for Entry<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.entry
}
}
impl<T> std::ops::DerefMut for Entry<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.entry
}
}
impl<T> PartialEq for Entry<T> {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl<T> Eq for Entry<T> {}
impl<T> PartialOrd for Entry<T> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<T> Ord for Entry<T> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.id.cmp(&other.id)
}
}
impl<T> std::hash::Hash for Entry<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.id.hash(state);
}
}
impl<T> Entry<T> {
pub fn new(item: T, id: Id<T>) -> Self {
Self { entry: item, id }
}
pub fn id(&self) -> Id<T> {
self.id
}
pub fn into_inner(self) -> T {
self.entry
}
}