Skip to main content

dambi/
slot_id.rs

1use std::num::NonZeroU32;
2use std::num::NonZeroU64;
3
4#[derive(Clone, Copy, Debug, PartialEq, Eq)]
5#[repr(C)]
6pub struct SlotId {
7    id_raw: NonZeroU64,
8}
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq)]
11#[repr(transparent)]
12pub struct SlotGen(NonZeroU32);
13
14impl SlotGen {
15    pub const MIN: Self = Self(NonZeroU32::MIN);
16
17    #[must_use]
18    pub const fn new(raw: u32) -> Option<Self> {
19        match NonZeroU32::new(raw) {
20            Some(raw) => Some(Self(raw)),
21            None => None,
22        }
23    }
24
25    pub const fn get(self) -> u32 {
26        self.0.get()
27    }
28
29    #[must_use]
30    pub const fn checked_add(self, other: u32) -> Option<Self> {
31        match self.0.checked_add(other) {
32            Some(raw) => Some(Self(raw)),
33            None => None,
34        }
35    }
36}
37
38impl SlotId {
39    #[must_use]
40    pub const fn from_parts(slot: u32, generation: SlotGen) -> Self {
41        let raw = ((generation.get() as u64) << 32) | (slot as u64);
42        // SAFETY: `generation` is `NonZeroU32`, so the high 32 bits of `raw`
43        // are non-zero, hence `raw != 0`.
44        Self {
45            id_raw: unsafe { NonZeroU64::new_unchecked(raw) },
46        }
47    }
48
49    pub const fn slot(self) -> u32 {
50        self.id_raw.get() as u32
51    }
52
53    pub const fn generation(self) -> SlotGen {
54        // SAFETY: `from_parts` placed a non-zero `SlotGen` in the high 32 bits.
55        SlotGen(unsafe { NonZeroU32::new_unchecked((self.id_raw.get() >> 32) as u32) })
56    }
57}