use std::num;
use o3::{base::num::bounded, depot, depot::capacity};
use crate::driver::{route, route::table};
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[repr(transparent)]
pub struct Capacity(bounded::NonZeroU32<1, { route::SLOT_MASK as u32 }>);
impl Capacity {
pub const fn fixed<const COUNT: usize>() -> Self {
const { assert!(COUNT > 0 && COUNT <= route::SLOT_MASK as usize, "capacity") };
Self(unsafe {
bounded::raw::nonzero_u32(num::NonZero::<u32>::MIN.saturating_add(COUNT as u32 - 1))
})
}
pub const fn nonzero(self) -> num::NonZero<usize> {
num::NonZero::<usize>::MIN.saturating_add(self.raw() as usize - 1)
}
pub(crate) const fn raw(self) -> u32 {
self.0.get()
}
pub const fn count(self) -> num::NonZero<u32> {
self.0.nonzero()
}
pub const fn entries(self) -> capacity::Count {
capacity::Count::new(self.0.get())
}
pub const fn scale<const FACTOR: u32>(self) -> capacity::Count {
const {
assert!(FACTOR != 0);
assert!(route::SLOT_MASK <= (u32::MAX / FACTOR) as u64);
}
capacity::Count::new(self.0.get() * FACTOR)
}
}
impl From<num::NonZero<u16>> for Capacity {
fn from(count: num::NonZero<u16>) -> Self {
const { assert!(u16::MAX as u64 <= route::SLOT_MASK, "capacity bound") };
Self(unsafe { bounded::raw::nonzero_u32(count.into()) })
}
}
impl TryFrom<usize> for Capacity {
type Error = table::Invalid;
fn try_from(actual: usize) -> Result<Self, Self::Error> {
bounded::NonZeroU32::from_usize(actual)
.map(Self)
.ok_or_else(|| table::Invalid::from_bounds(actual, 1, route::SLOT_MASK as usize))
}
}
impl TryFrom<capacity::Count> for Capacity {
type Error = table::Invalid;
fn try_from(actual: capacity::Count) -> Result<Self, Self::Error> {
bounded::NonZeroU32::new(actual.raw())
.map(Self)
.ok_or_else(|| table::Invalid::from_bounds(actual.get(), 1, route::SLOT_MASK as usize))
}
}
impl From<Capacity> for table::Capacity {
fn from(capacity: Capacity) -> Self {
Self(capacity::Count::new(capacity.0.get()))
}
}
unsafe impl depot::raw::Count for Capacity {
const MAX: u32 = route::SLOT_MASK as u32;
fn count(self) -> capacity::Count {
capacity::Count::new(self.0.get())
}
}