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(
17            unsafe {
18                bounded::raw::NonZeroProof::assume(
19                    num::NonZero::<u32>::MIN.saturating_add(COUNT as u32 - 1),
20                )
21            }
22            .retain(),
23        )
24    }
25
26    pub const fn nonzero(self) -> num::NonZero<usize> {
27        num::NonZero::<usize>::MIN.saturating_add(self.raw() as usize - 1)
28    }
29
30    pub(crate) const fn raw(self) -> u32 {
31        self.0.get()
32    }
33
34    pub const fn count(self) -> num::NonZero<u32> {
35        self.0.nonzero()
36    }
37
38    pub const fn entries(self) -> capacity::Count {
39        capacity::Count::new(self.0.get())
40    }
41
42    /// Scales this validated connection domain into a collection count.
43    ///
44    /// The factor is part of the type-level call site, so the complete
45    /// connection domain must fit before any value can be scaled.
46    pub const fn scale<const FACTOR: u32>(self) -> capacity::Count {
47        const {
48            assert!(FACTOR != 0);
49            assert!(route::SLOT_MASK <= (u32::MAX / FACTOR) as u64);
50        }
51        capacity::Count::new(self.0.get() * FACTOR)
52    }
53}
54
55impl From<num::NonZero<u16>> for Capacity {
56    fn from(count: num::NonZero<u16>) -> Self {
57        const { assert!(u16::MAX as u64 <= route::SLOT_MASK, "capacity bound") };
58        // SAFETY: the const bound keeps every nonzero u16 count within 1..=SLOT_MASK.
59        Self(unsafe { bounded::raw::NonZeroProof::assume(count.into()) }.retain())
60    }
61}
62
63impl TryFrom<usize> for Capacity {
64    type Error = table::Invalid;
65
66    fn try_from(actual: usize) -> Result<Self, Self::Error> {
67        bounded::NonZeroU32::from_usize(actual)
68            .map(Self)
69            .ok_or_else(|| table::Invalid::from_bounds(actual, 1, route::SLOT_MASK as usize))
70    }
71}
72
73impl TryFrom<capacity::Count> for Capacity {
74    type Error = table::Invalid;
75
76    fn try_from(actual: capacity::Count) -> Result<Self, Self::Error> {
77        bounded::NonZeroU32::new(actual.raw())
78            .map(Self)
79            .ok_or_else(|| table::Invalid::from_bounds(actual.get(), 1, route::SLOT_MASK as usize))
80    }
81}
82
83impl From<Capacity> for table::Capacity {
84    fn from(capacity: Capacity) -> Self {
85        Self(capacity::Count::new(capacity.0.get()))
86    }
87}
88
89// SAFETY: the retained nonzero connection domain is bounded by SLOT_MASK, which is one immutable u32 extent.
90unsafe impl depot::raw::Count for Capacity {
91    const MAX: u32 = route::SLOT_MASK as u32;
92
93    fn count(self) -> capacity::Count {
94        capacity::Count::new(self.0.get())
95    }
96}