Skip to main content

dope_core/driver/route/table/
conn.rs

1use std::num;
2
3use o3::{base::num::bounded, depot, depot::capacity};
4
5use crate::driver::{route, route::table};
6
7/// A non-empty target-table capacity with one encodable slot left as a sentinel.
8#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
9#[repr(transparent)]
10pub struct Capacity(bounded::NonZeroU32<1, { route::SLOT_MASK as u32 }>);
11
12impl Capacity {
13    pub const fn fixed<const COUNT: usize>() -> Self {
14        const { assert!(COUNT > 0 && COUNT <= route::SLOT_MASK as usize, "capacity") };
15        // SAFETY: the const bound keeps the count in 1..=SLOT_MASK.
16        Self(unsafe {
17            bounded::raw::nonzero_u32(num::NonZero::<u32>::MIN.saturating_add(COUNT as u32 - 1))
18        })
19    }
20
21    pub const fn nonzero(self) -> num::NonZero<usize> {
22        num::NonZero::<usize>::MIN.saturating_add(self.raw() as usize - 1)
23    }
24
25    pub(crate) const fn raw(self) -> u32 {
26        self.0.get()
27    }
28
29    pub const fn count(self) -> num::NonZero<u32> {
30        self.0.nonzero()
31    }
32
33    pub const fn entries(self) -> capacity::Count {
34        capacity::Count::new(self.0.get())
35    }
36
37    /// Scales this validated connection domain into a collection count.
38    ///
39    /// The factor is part of the type-level call site, so the complete
40    /// connection domain must fit before any value can be scaled.
41    pub const fn scale<const FACTOR: u32>(self) -> capacity::Count {
42        const {
43            assert!(FACTOR != 0);
44            assert!(route::SLOT_MASK <= (u32::MAX / FACTOR) as u64);
45        }
46        capacity::Count::new(self.0.get() * FACTOR)
47    }
48}
49
50impl From<num::NonZero<u16>> for Capacity {
51    fn from(count: num::NonZero<u16>) -> Self {
52        const { assert!(u16::MAX as u64 <= route::SLOT_MASK, "capacity bound") };
53        // SAFETY: the const bound keeps every nonzero u16 count within 1..=SLOT_MASK.
54        Self(unsafe { bounded::raw::nonzero_u32(count.into()) })
55    }
56}
57
58impl TryFrom<usize> for Capacity {
59    type Error = table::Invalid;
60
61    fn try_from(actual: usize) -> Result<Self, Self::Error> {
62        bounded::NonZeroU32::from_usize(actual)
63            .map(Self)
64            .ok_or_else(|| table::Invalid::from_bounds(actual, 1, route::SLOT_MASK as usize))
65    }
66}
67
68impl TryFrom<capacity::Count> for Capacity {
69    type Error = table::Invalid;
70
71    fn try_from(actual: capacity::Count) -> Result<Self, Self::Error> {
72        bounded::NonZeroU32::new(actual.raw())
73            .map(Self)
74            .ok_or_else(|| table::Invalid::from_bounds(actual.get(), 1, route::SLOT_MASK as usize))
75    }
76}
77
78impl From<Capacity> for table::Capacity {
79    fn from(capacity: Capacity) -> Self {
80        Self(capacity::Count::new(capacity.0.get()))
81    }
82}
83
84// SAFETY: the retained nonzero connection domain is bounded by SLOT_MASK, which is one immutable u32 extent.
85unsafe impl depot::raw::Count for Capacity {
86    const MAX: u32 = route::SLOT_MASK as u32;
87
88    fn count(self) -> capacity::Count {
89        capacity::Count::new(self.0.get())
90    }
91}