use std::{mem, num::NonZero};
pub use domain::Domain;
pub use key::Key;
use crate::{alloc, depot, depot::capacity};
mod domain;
mod key;
pub trait Extent: Copy {
#[doc(hidden)]
fn get(self) -> usize;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Count(u32);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Error {
requested: usize,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Shortage {
pub requested: NonZero<usize>,
pub available: usize,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Reason {
Full,
Allocation(alloc::Error),
}
impl Count {
pub const EMPTY: Self = Self(0);
pub const MAX: Self = Self(u32::MAX);
#[must_use]
pub const fn new(count: u32) -> Self {
Self(count)
}
pub(in crate::depot) const fn try_index<E: Copy>(
count: usize,
maximum: usize,
error: E,
) -> Result<Self, E> {
if count > u32::MAX as usize || (count != 0 && count - 1 > maximum) {
return Err(error);
}
Ok(Self(count as u32))
}
pub(in crate::depot) const fn try_count<E: Copy>(count: usize, error: E) -> Result<Self, E> {
Self::try_index(count, u32::MAX as usize, error)
}
#[inline]
pub fn try_nonzero(count: NonZero<usize>) -> Result<NonZero<u32>, Error> {
Self::try_narrow(count, Error::new(count.get()))
}
pub(in crate::depot) fn try_narrow<E: Copy>(
count: NonZero<usize>,
error: E,
) -> Result<NonZero<u32>, E> {
NonZero::<u32>::try_from(count).map_err(|_| error)
}
#[must_use]
pub const fn get(self) -> usize {
self.0 as usize
}
#[must_use]
pub const fn raw(self) -> u32 {
self.0
}
#[must_use]
pub const fn nonzero(self) -> Option<NonZero<u32>> {
NonZero::new(self.0)
}
}
impl TryFrom<usize> for Count {
type Error = Error;
fn try_from(count: usize) -> Result<Self, Self::Error> {
Self::try_count(count, Error::new(count))
}
}
impl Extent for Count {
fn get(self) -> usize {
self.0 as usize
}
}
impl Extent for usize {
fn get(self) -> usize {
self
}
}
impl Error {
pub(crate) const fn new(count: usize) -> Self {
Self { requested: count }
}
#[must_use]
pub const fn requested(self) -> usize {
self.requested
}
}
const _: () = assert!(mem::size_of::<Reason>() == 1);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct Limit<const MAX: usize>(NonZero<u32>);
impl<const MAX: usize> Limit<MAX> {
pub const MAX: usize = if MAX > u32::MAX as usize {
u32::MAX as usize
} else {
MAX
};
pub const fn new(value: usize) -> Option<Self> {
if value == 0 || value > Self::MAX {
return None;
}
Some(Self(NonZero::<u32>::MIN.saturating_add(value as u32 - 1)))
}
pub const fn fixed<const N: usize>() -> Self {
const {
assert!(N != 0 && N <= Self::MAX);
}
Self(NonZero::<u32>::MIN.saturating_add(N as u32 - 1))
}
pub const fn get(self) -> usize {
self.0.get() as usize
}
pub const fn count(self) -> NonZero<u32> {
self.0
}
}
unsafe impl<const MAX: usize> alloc::raw::Extent for Limit<MAX> {
fn len(&self) -> usize {
self.0.get() as usize
}
}
unsafe impl alloc::raw::Extent for capacity::Count {
fn len(&self) -> usize {
self.0 as usize
}
}
unsafe impl depot::raw::Count for capacity::Count {
fn count(self) -> capacity::Count {
self
}
}
unsafe impl depot::raw::Count for NonZero<u32> {
const MIN: u32 = 1;
fn count(self) -> capacity::Count {
capacity::Count::new(self.get())
}
}
unsafe impl<const MAX: usize> depot::raw::Count for Limit<MAX> {
const MIN: u32 = 1;
const MAX: u32 = Limit::<MAX>::MAX as u32;
fn count(self) -> capacity::Count {
capacity::Count::new(self.0.get())
}
}
unsafe impl alloc::raw::TailExtent for capacity::Count {
type Index = u32;
fn indices(self) -> impl Iterator<Item = Self::Index> {
0..self.raw()
}
}
const _: () = {
assert!(mem::size_of::<Limit<65536>>() == mem::size_of::<u32>());
assert!(mem::size_of::<Option<Limit<65536>>>() == mem::size_of::<u32>());
};
pub enum Physical {}
impl crate::depot::Predicate for Physical {}