use core::fmt::Debug;
pub unsafe trait Id: Sized + Copy + PartialEq + Eq + Debug {}
#[derive(Debug, PartialEq, Eq)]
pub struct Unique<I: Id> {
id: I,
}
impl<I: Id> Unique<I> {
pub const unsafe fn new(id: I) -> Self {
Self { id }
}
#[must_use]
pub const fn into_inner(self) -> I {
self.id
}
}
unsafe impl<I: Id> Sync for Unique<I> {}
#[cfg(debug_assertions)]
#[cfg(target_has_atomic = "64")]
mod checked {
use super::Id;
use super::Unique;
use core::num::NonZeroU64;
use core::sync::atomic;
use core::sync::atomic::AtomicU64;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Checked(NonZeroU64);
impl Checked {
#[must_use]
pub fn new() -> Unique<Self> {
static COUNTER: AtomicU64 = AtomicU64::new(1);
const MAX_ID: u64 = u64::MAX >> 1;
let id = COUNTER.fetch_add(1, atomic::Ordering::Relaxed);
if id >= MAX_ID {
std::process::abort();
}
let id = Self(unsafe { NonZeroU64::new_unchecked(id) });
unsafe { Unique::new(id) }
}
}
unsafe impl Id for Checked {}
}
#[cfg(target_has_atomic = "64")]
mod debug_checked {
use super::Id;
use super::Unique;
#[cfg(debug_assertions)]
use crate::pin_list::id;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugChecked {
#[cfg(debug_assertions)]
checked: id::checked::Checked,
}
impl DebugChecked {
#[must_use]
pub unsafe fn new() -> Unique<Self> {
let this = Self {
#[cfg(debug_assertions)]
checked: id::checked::Checked::new().into_inner(),
};
unsafe { Unique::new(this) }
}
}
unsafe impl Id for DebugChecked {}
}
#[cfg(target_has_atomic = "64")]
pub use debug_checked::DebugChecked;