shared-ids 0.11.0

New types for different IDs
Documentation
use serde::{Deserialize, Serialize};
use std::{fmt::Debug, hash::Hash, marker::PhantomData};

#[doc(hidden)]
pub use paste::paste;

#[macro_export]
macro_rules! id_type {
    ($vis:vis $name:ident) => {
        #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
        #[doc(hidden)]
        $vis struct $name;
        impl $crate::IdType for $name {
            const NAME: &'static str = ::std::stringify!($name);
        }
        $crate::paste! {
            $vis type [< $name Id >] = $crate::Id<$name>;
        }
    };
}

id_type!(pub Client);
id_type!(pub Request);
id_type!(pub Replica);

pub trait IdType: Debug + Clone + Copy + Hash + PartialEq + Eq + PartialOrd + Ord {
    const NAME: &'static str;
}

#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[repr(transparent)]
#[serde(transparent, bound = "")]
pub struct Id<T: IdType> {
    id: u64,
    phantom_data: PhantomData<T>,
}

impl<T: IdType> Id<T> {
    pub const fn first() -> Self {
        Self::from_u64(0)
    }

    pub const fn from_u64(id: u64) -> Self {
        Self {
            id,
            phantom_data: PhantomData,
        }
    }

    pub const fn as_u64(&self) -> u64 {
        self.id
    }

    pub fn as_mut_u64(&mut self) -> &mut u64 {
        &mut self.id
    }
}

impl<T: IdType> std::fmt::Display for Id<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}Id({})", T::NAME, self.id)
    }
}

impl<T: IdType> std::fmt::Debug for Id<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}Id({})", T::NAME, self.id)
    }
}

pub struct IdIter<T: IdType> {
    next: Id<T>,
}

impl<T: IdType> Default for IdIter<T> {
    fn default() -> Self {
        Self { next: Id::first() }
    }
}

impl<T: IdType> Iterator for IdIter<T> {
    type Item = Id<T>;

    fn next(&mut self) -> Option<Self::Item> {
        let ret = self.next;

        let id = self.next.as_mut_u64();

        if let Some(next) = id.checked_add(1) {
            *id = next;
            Some(ret)
        } else {
            None
        }
    }
}