Skip to main content

dope_core/driver/
token.rs

1use core::marker::PhantomData;
2use core::num::{NonZeroU32, NonZeroU64};
3
4mod slab;
5
6pub use slab::{Key, KeyParts, TokenCapacity, TokenCellSlab, TokenSlab, TokenSlabVacantEntry};
7
8pub const ROUTE_FRAMEWORK: u8 = 255;
9
10pub const ROUTE_SHIFT: u32 = 56;
11pub const KIND_SHIFT: u32 = 48;
12const EPOCH_SHIFT: u32 = 24;
13const ROUTE_MASK: u64 = 0xFF << ROUTE_SHIFT;
14const KIND_MASK: u64 = 0xFF << KIND_SHIFT;
15const TARGET_MASK: u64 = !KIND_MASK;
16pub const SLOT_BITS: u32 = 24;
17const EPOCH_BITS: u32 = 24;
18pub const SLOT_MASK: u64 = (1 << SLOT_BITS) - 1;
19pub const EPOCH_MASK: u64 = (1 << EPOCH_BITS) - 1;
20
21pub struct KeyTag<const ROUTE: u8, const KIND: u8 = 0>;
22
23pub trait TokenTag {
24    const ROUTE: u8;
25    const KIND: u8;
26    const MASK: u64;
27    const VALUE: u64;
28}
29
30impl<const ROUTE: u8, const KIND: u8> TokenTag for KeyTag<ROUTE, KIND> {
31    const ROUTE: u8 = ROUTE;
32    const KIND: u8 = KIND;
33    const MASK: u64 = ROUTE_MASK | if KIND == 0 { 0 } else { KIND_MASK };
34    const VALUE: u64 = (ROUTE as u64) << ROUTE_SHIFT | (KIND as u64) << KIND_SHIFT;
35}
36
37pub mod kind {
38    pub const ACCEPT: u8 = 1;
39    pub const RECV: u8 = 2;
40    pub const SEND: u8 = 3;
41    pub const TIMER: u8 = 4;
42    pub const SOCKET: u8 = 5;
43    pub const CONNECT: u8 = 6;
44    pub const SHUTDOWN: u8 = 7;
45    pub const SETSOCKOPT: u8 = 8;
46    pub const WRITE: u8 = 9;
47    pub const SYNC: u8 = 10;
48    pub const OPEN: u8 = 11;
49    pub const READ: u8 = 12;
50    pub const RECV_DISCARD: u8 = 14;
51    pub const CREATE: u8 = 15;
52    pub const CLOSE_PREP: u8 = 16;
53    pub const CLOSE: u8 = 17;
54    pub const STAT: u8 = 18;
55    pub const ONE_SHOT: u8 = 19;
56    pub const TASK_QUEUE: u8 = 21;
57    pub const RECV_CREDIT_HELD: u8 = 22;
58    pub const RECV_CREDIT_RELEASED: u8 = 23;
59}
60
61#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Default)]
62#[repr(transparent)]
63pub struct SlotIndex(u32);
64
65impl SlotIndex {
66    pub const ZERO: Self = Self(0);
67
68    pub const fn try_new(raw: u32) -> Option<Self> {
69        if (raw as u64) <= SLOT_MASK {
70            Some(Self::from_bounded(raw))
71        } else {
72            None
73        }
74    }
75
76    pub(crate) const fn from_bounded(raw: u32) -> Self {
77        debug_assert!((raw as u64) <= SLOT_MASK);
78        Self(raw)
79    }
80
81    pub const fn raw(self) -> u32 {
82        self.0
83    }
84}
85
86impl From<u16> for SlotIndex {
87    fn from(raw: u16) -> Self {
88        Self(raw as u32)
89    }
90}
91
92#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
93#[repr(transparent)]
94pub struct Epoch(NonZeroU32);
95
96impl Epoch {
97    pub const INITIAL: Self = Self(NonZeroU32::MIN);
98    pub const MAX: Self = Self(NonZeroU32::MIN.saturating_add(EPOCH_MASK as u32 - 1));
99
100    pub const fn new(raw: u32) -> Option<Self> {
101        match NonZeroU32::new(raw) {
102            Some(raw) if raw.get() <= EPOCH_MASK as u32 => Some(Self(raw)),
103            Some(_) | None => None,
104        }
105    }
106
107    pub const fn raw(self) -> u32 {
108        self.0.get()
109    }
110
111    pub const fn next(self) -> Option<Self> {
112        if self.0.get() < EPOCH_MASK as u32 {
113            Some(Self(self.0.saturating_add(1)))
114        } else {
115            None
116        }
117    }
118}
119
120#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
121#[repr(transparent)]
122pub struct Token(NonZeroU64, PhantomData<*mut ()>);
123
124impl Token {
125    pub const fn new(route: u8, slot: SlotIndex, epoch: Epoch) -> Self {
126        let raw = Self::pack(route, slot, epoch.raw());
127        // `Epoch` proves that the target bits are nonzero.
128        Self::from_proven_target(raw)
129    }
130
131    pub const fn framework(slot: SlotIndex) -> Self {
132        let raw = Self::pack(ROUTE_FRAMEWORK, slot, 0);
133        // `ROUTE_FRAMEWORK` proves that the target bits are nonzero.
134        Self::from_proven_target(raw)
135    }
136
137    pub const fn with_kind(self, kind: u8) -> Self {
138        let raw = (self.0.get() & !KIND_MASK) | ((kind as u64) << KIND_SHIFT);
139        // Every `Token` retains nonzero target bits independently of
140        // its kind, so replacing the kind cannot produce zero.
141        Self::from_proven_target(raw)
142    }
143
144    const fn pack(route: u8, slot: SlotIndex, epoch: u32) -> u64 {
145        ((route as u64) << ROUTE_SHIFT) | ((epoch as u64) << EPOCH_SHIFT) | slot.0 as u64
146    }
147
148    const fn from_proven_target(raw: u64) -> Self {
149        Self(
150            // SAFETY: this private wrapper's callers prove that the
151            // kind-independent target is nonzero.
152            unsafe { NonZeroU64::new_unchecked(raw) },
153            PhantomData,
154        )
155    }
156
157    pub const fn try_from_raw(raw: u64) -> Option<Self> {
158        if raw & TARGET_MASK == 0 {
159            return None;
160        }
161        Some(Self::from_proven_target(raw))
162    }
163
164    pub const fn raw(self) -> u64 {
165        self.0.get()
166    }
167
168    pub const fn route(self) -> u8 {
169        (self.0.get() >> ROUTE_SHIFT) as u8
170    }
171
172    pub const fn kind(self) -> u8 {
173        ((self.0.get() & KIND_MASK) >> KIND_SHIFT) as u8
174    }
175
176    pub const fn slot(self) -> SlotIndex {
177        SlotIndex::from_bounded((self.0.get() & SLOT_MASK) as u32)
178    }
179
180    pub const fn epoch(self) -> Option<Epoch> {
181        Epoch::new(self.epoch_raw())
182    }
183
184    pub const fn epoch_raw(self) -> u32 {
185        ((self.0.get() >> EPOCH_SHIFT) & EPOCH_MASK) as u32
186    }
187
188    pub const fn same_target(self, other: Self) -> bool {
189        self.0.get() & !KIND_MASK == other.0.get() & !KIND_MASK
190    }
191
192    #[allow(private_bounds)]
193    pub const fn parts<Tag: TokenTag>(self) -> Option<KeyParts<Tag>> {
194        if self.raw() & Tag::MASK != Tag::VALUE {
195            return None;
196        }
197        KeyParts::new(self.slot().raw(), self.epoch_raw())
198    }
199
200    #[allow(private_bounds)]
201    pub const fn from_key<Tag: TokenTag>(key: Key<Tag>) -> Self {
202        let raw = Self::pack(Tag::ROUTE, key.slot(), key.generation().get())
203            | ((Tag::KIND as u64) << KIND_SHIFT);
204        // `SlabGeneration` proves that the target is nonzero.
205        Self::from_proven_target(raw)
206    }
207
208    #[doc(hidden)]
209    #[allow(private_bounds)]
210    pub const fn from_parts<Tag: TokenTag>(parts: KeyParts<Tag>) -> Self {
211        let raw = Self::pack(Tag::ROUTE, parts.slot(), parts.generation().get())
212            | ((Tag::KIND as u64) << KIND_SHIFT);
213        // `KeyParts` proves that the generation, and therefore the
214        // kind-independent target, is nonzero.
215        Self::from_proven_target(raw)
216    }
217}
218
219pub const SHUTDOWN: Token = Token::framework(SlotIndex::ZERO).with_kind(kind::SHUTDOWN);