use super::Identifier;
#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[repr(transparent)]
pub struct Id<T = usize>(pub T);
impl<T> Id<T> {
pub const fn new(id: T) -> Self {
Self(id)
}
#[allow(clippy::should_implement_trait)]
pub fn default() -> Self
where
T: Default,
{
Self::new(T::default())
}
pub fn one() -> Self
where
T: num_traits::One,
{
Self::new(T::one())
}
pub fn zero() -> Self
where
T: num_traits::Zero,
{
Self::new(T::zero())
}
#[cfg(feature = "rand")]
pub fn random() -> Self
where
rand_distr::StandardUniform: rand_distr::Distribution<T>,
{
use rand::Rng;
let mut rng = rand::rng();
Self::new(rng.random())
}
pub const fn get(&self) -> &T {
&self.0
}
pub const fn get_mut(&mut self) -> &mut T {
&mut self.0
}
#[inline]
pub fn value(self) -> T {
self.0
}
pub const fn replace(&mut self, id: T) -> T {
core::mem::replace(self.get_mut(), id)
}
pub fn set(&mut self, id: T) -> &mut Self {
*self.get_mut() = id;
self
}
pub const fn swap(&mut self, id: &mut Id<T>) {
core::mem::swap(self.get_mut(), id.get_mut())
}
pub fn take(&mut self) -> T
where
T: Default,
{
core::mem::take(self.get_mut())
}
pub fn with<U>(self, id: U) -> Id<U> {
Id::new(id)
}
pub fn map<U, F>(self, f: F) -> Id<U>
where
F: FnOnce(T) -> U,
{
Id::new(f(self.value()))
}
pub fn step(&mut self) -> T
where
T: num_traits::One,
for<'a> &'a T: core::ops::Add<T, Output = T>,
{
self.replace(self.get() + T::one())
}
pub const fn view(&self) -> Id<&T> {
Id::new(self.get())
}
pub const fn view_mut(&mut self) -> Id<&mut T> {
Id::new(self.get_mut())
}
}
impl Id<usize> {
pub fn atomic() -> Self {
use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
static COUNTER: AtomicUsize = AtomicUsize::new(1);
Self::new(COUNTER.fetch_add(1, Relaxed))
}
pub fn atomic_step(&mut self) -> usize {
use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
static COUNTER: AtomicUsize = AtomicUsize::new(1);
self.replace(COUNTER.fetch_add(1, Relaxed))
}
}
#[cfg(feature = "uuid")]
impl Id<uuid::Uuid> {
pub fn v3(namespace: &uuid::Uuid, name: &[u8]) -> Self {
let id = uuid::Uuid::new_v3(namespace, name);
Self::new(id)
}
#[cfg(all(feature = "rng", feature = "uuid"))]
pub fn v4() -> Self {
let id = uuid::Uuid::new_v4();
Self::new(id)
}
}
impl<T> Default for Id<T>
where
T: Default,
{
fn default() -> Self {
Self::new(T::default())
}
}
impl<T> Identifier for Id<T> {
seal!();
}