use crate::driver::BackendToken;
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct TokenSlot(u16);
impl TokenSlot {
#[inline(always)]
pub fn from_index(index: usize) -> Self {
Self(u16::try_from(index).expect("dope: token slot index exceeds u16 range"))
}
#[inline(always)]
pub const fn from_raw(raw: u16) -> Self {
Self(raw)
}
#[inline(always)]
pub const fn as_usize(self) -> usize {
self.0 as usize
}
#[inline(always)]
pub const fn raw(self) -> u16 {
self.0
}
}
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct TokenEpoch(u32);
impl TokenEpoch {
pub const MAX: u32 = (1 << 24) - 1;
#[inline(always)]
pub const fn from_raw(raw: u32) -> Self {
assert!(
raw <= Self::MAX,
"dope: token epoch exceeds 24-bit user_data budget",
);
Self(raw)
}
#[inline(always)]
pub const fn raw(self) -> u32 {
self.0
}
#[inline(always)]
pub fn next(seq: &mut u32) -> Self {
*seq = seq.wrapping_add(1) & Self::MAX;
Self::from_raw(*seq)
}
}
pub trait WirePad: Copy + 'static {
const ZERO: Self;
}
impl WirePad for () {
const ZERO: () = ();
}
impl WirePad for u8 {
const ZERO: u8 = 0;
}
#[repr(C, packed)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Token<P: WirePad> {
slot: TokenSlot,
epoch: TokenEpoch,
_pad: P,
}
impl<P: WirePad> Token<P> {
#[inline(always)]
pub const fn new(slot: TokenSlot, epoch: TokenEpoch) -> Self {
Self {
slot,
epoch,
_pad: P::ZERO,
}
}
#[inline(always)]
pub fn from_index(index: usize, epoch: TokenEpoch) -> Self {
Self::new(TokenSlot::from_index(index), epoch)
}
#[inline(always)]
pub fn from_index_raw(index: usize, epoch: u32) -> Self {
Self::from_index(index, TokenEpoch::from_raw(epoch))
}
#[inline(always)]
pub fn next_for_slot(index: usize, seq: &mut u32) -> Self {
Self::from_index(index, TokenEpoch::next(seq))
}
#[inline(always)]
pub const fn parts(self) -> (usize, u32) {
(self.slot.as_usize(), self.epoch.raw())
}
#[inline(always)]
pub fn slot_raw(self) -> u16 {
self.slot.raw()
}
#[inline(always)]
pub fn epoch_raw(self) -> u32 {
self.epoch.raw()
}
}
impl<P: WirePad> BackendToken for Token<P> {
#[inline(always)]
fn parts(self) -> (usize, u32) {
Self::parts(self)
}
#[inline(always)]
fn next_for_slot(index: usize, seq: &mut u32) -> Self {
Self::next_for_slot(index, seq)
}
#[inline(always)]
fn from_index_raw(index: usize, epoch: u32) -> Self {
Self::from_index_raw(index, epoch)
}
}