use std::fmt::Debug;
pub trait Identifier: Eq + Debug + Copy + Send + Sync {
type AtomicType: RollingCounter<NonAtomic = Self>;
type ComparisonMaySpuriouslyEq: crate::core::sealed::Boolean;
}
pub trait RollingCounter {
const DEFAULT: Self;
type NonAtomic;
fn next(&self) -> Self::NonAtomic;
}
macro_rules! impl_identifier {
(comp u64) => {
crate::core::False
};
(comp u128) => {
crate::core::False
};
(comp $id: ty) => {
crate::core::False
};
($id: ty, $atom: ty) => {
impl Identifier for $id {
type AtomicType = $atom;
type ComparisonMaySpuriouslyEq = impl_identifier!(comp $id);
}
impl RollingCounter for $atom {
const DEFAULT: Self = Self::new(0);
type NonAtomic = $id;
fn next(&self) -> Self::NonAtomic {
self.fetch_add(1, core::sync::atomic::Ordering::Relaxed)
}
}
};
}
impl_identifier!(u8, portable_atomic::AtomicU8);
impl_identifier!(u16, portable_atomic::AtomicU16);
impl_identifier!(u32, portable_atomic::AtomicU32);
impl_identifier!(u64, portable_atomic::AtomicU64);
impl_identifier!(u128, portable_atomic::AtomicU128);
#[derive(Debug, Clone, Copy)]
pub struct IdMismatch<T: Identifier> {
pub cell: T,
pub token: T,
}
impl<T: Identifier> ::core::fmt::Display for IdMismatch<T> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
write!(f, "{:?}", self)
}
}
#[macro_export]
macro_rules! runtime_token {
($(#[$meta: meta])* $vis: vis $id: ident) => {
runtime_token!($(#[meta])* $vis $id: u16);
};
($(#[$meta: meta])* $vis: vis $id: ident: $ty: ty) => {
$crate::paste! {
$vis use [<__ $id _mod__ >]::$id;
#[allow(nonstandard_style)]
mod [<__ $id _mod__ >] {
use core::convert::Infallible;
use $crate::core::UnscopedToken;
use $crate::runtime_token_support::{Identifier, IdMismatch, RollingCounter};
static COUNTER: <$ty as Identifier>::AtomicType = <<$ty as Identifier>::AtomicType as RollingCounter>::DEFAULT;
$(#[$meta])*
#[derive(::core::fmt::Debug)]
pub struct $id($ty);
impl UnscopedToken for $id {
type ConstructionError = Infallible;
fn try_new() -> Result<Self, Self::ConstructionError> {
let id = COUNTER.next();
Ok(Self(id))
}
}
impl $crate::core::TokenTrait for $id {
type ComparisonMaySpuriouslyEq = $crate::core::False;
type RunError = Infallible;
type Identifier = $ty;
type ComparisonError = IdMismatch<$ty>;
type Branded<'a> = Self;
fn with_token<R, F: for<'a> FnOnce(Self::Branded<'a>) -> R>(f: F) -> Result<R, Self::RunError> {
Ok(f(Self::new()))
}
fn identifier(&self) -> Self::Identifier { self.0 }
fn compare(&self, id: &Self::Identifier) -> Result<(), Self::ComparisonError> {
if *id == self.0 { Ok(()) } else { Err(IdMismatch { cell: *id, token: self.0 }) }
}
}
}
}
};
($($(#[$meta: meta])* $vis: vis $id: ident),*) => {
$($crate::runtime_token!($(#[meta])* $vis $id);)*
};
($($(#[$meta: meta])* $vis: vis $id: ident: $ty: ty),*) => {
$($crate::runtime_token!($(#[meta])* $vis $id: $ty);)*
};
}