dope_core/driver/route/table/
capacity.rs1use std::num;
2
3use o3::{base::num::bounded, depot::capacity};
4
5use crate::driver::{
6 route,
7 route::{
8 indices,
9 table::{
10 Iter, bounds,
11 bounds::{Outside, Slot},
12 },
13 },
14};
15
16#[derive(Clone, Copy, PartialEq, Eq, Debug)]
18#[repr(transparent)]
19pub struct Capacity(pub(in crate::driver) capacity::Count);
20
21impl Capacity {
22 pub fn try_nonzero(
24 count: num::NonZero<u32>,
25 ) -> Result<bounded::NonZeroU32<1, { route::SLOT_MASK as u32 + 1 }>, super::Invalid> {
26 Self::try_from(count.get() as usize)?;
27 Ok(unsafe { bounded::raw::nonzero_u32(count) })
29 }
30
31 pub const fn count(self) -> capacity::Count {
32 self.0
33 }
34
35 pub(crate) const fn raw(self) -> u32 {
36 self.0.raw()
37 }
38
39 pub(crate) fn span(self) -> Option<num::NonZero<u32>> {
40 num::NonZero::<u32>::new(self.raw())
41 }
42
43 pub const fn contains(self, index: indices::SlotIndex) -> bool {
44 index.raw() < self.raw()
45 }
46
47 pub const fn next(self, index: indices::SlotIndex) -> Option<indices::SlotIndex> {
49 let raw = index.raw() + 1;
50 if raw < self.raw() {
51 Some(indices::SlotIndex::from_field(raw as u64))
52 } else {
53 None
54 }
55 }
56
57 pub const fn excludes(self, index: indices::SlotIndex) -> Option<bounds::Excluded> {
58 if self.contains(index) {
59 None
60 } else {
61 Some(bounds::Excluded::new(index, self))
62 }
63 }
64
65 pub fn slot(self, index: usize) -> Result<indices::SlotIndex, Slot> {
66 let slot = indices::SlotIndex::try_from(index).map_err(|outside| {
67 Slot::Abi(Outside::new(
68 outside.actual(),
69 route::SLOT_MASK as usize + 1,
70 ))
71 })?;
72 if self.contains(slot) {
73 Ok(slot)
74 } else {
75 Err(Slot::Capacity(Outside::new(index, self.raw() as usize)))
76 }
77 }
78}
79
80impl From<bounded::NonZeroU32<1, { route::SLOT_MASK as u32 + 1 }>> for Capacity {
81 fn from(count: bounded::NonZeroU32<1, { route::SLOT_MASK as u32 + 1 }>) -> Self {
82 Self(capacity::Count::new(count.get()))
83 }
84}
85
86impl TryFrom<usize> for Capacity {
87 type Error = super::Invalid;
88
89 fn try_from(actual: usize) -> Result<Self, Self::Error> {
90 let maximum = route::SLOT_MASK as usize + 1;
91 if actual > maximum {
92 return Err(super::Invalid::from_bounds(actual, 0, maximum));
93 }
94 Ok(Self(capacity::Count::new(actual as u32)))
95 }
96}
97
98impl IntoIterator for Capacity {
99 type Item = indices::SlotIndex;
100 type IntoIter = Iter;
101
102 fn into_iter(self) -> Self::IntoIter {
103 Iter(0..self.raw())
104 }
105}