pub mod bytes;
pub mod pool;
pub mod queue;
pub mod resident;
mod sealed;
pub mod storage;
pub mod view;
pub mod write;
use std::{error, fmt, ops};
pub(crate) use sealed::Seal;
pub use sealed::{Frozen, Layout, Lease, Plan, Pool};
pub trait PrefixLength {
fn prefix_len(&self) -> usize;
}
pub trait PrefixConsumer: PrefixLength {
fn consume_validated_prefix(&mut self, proof: PrefixProof);
fn try_consume_prefix(
&mut self,
amount: usize,
) -> Result<ValidatedPrefix<'_, Self>, CapacityError> {
ValidatedPrefix::try_new(self, amount)
}
fn consume_prefix_up_to(&mut self, requested: usize) -> usize {
let prefix = ValidatedPrefix::up_to(self, requested);
let amount = prefix.len();
prefix.commit();
amount
}
}
#[doc(hidden)]
pub struct PrefixProof {
amount: usize,
}
impl PrefixProof {
fn new(amount: usize) -> Self {
Self { amount }
}
pub const fn amount(&self) -> usize {
self.amount
}
}
#[must_use]
pub struct ValidatedPrefix<'a, T: PrefixConsumer + ?Sized> {
target: &'a mut T,
proof: PrefixProof,
}
impl<'a, T: PrefixConsumer + ?Sized> ValidatedPrefix<'a, T> {
fn try_new(target: &'a mut T, amount: usize) -> Result<Self, CapacityError> {
let available = target.prefix_len();
if amount > available {
return Err(CapacityError::new(amount, available));
}
Ok(Self {
target,
proof: PrefixProof::new(amount),
})
}
fn up_to(target: &'a mut T, requested: usize) -> Self {
let amount = requested.min(target.prefix_len());
Self {
target,
proof: PrefixProof::new(amount),
}
}
const fn len(&self) -> usize {
self.proof.amount()
}
}
impl<T: PrefixConsumer + ?Sized> ValidatedPrefix<'_, T> {
pub fn commit(self) {
self.target.consume_validated_prefix(self.proof);
}
}
pub const BLOCK_CAPACITY: u32 = 64 * 1024;
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct CapacityError {
attempted: usize,
capacity: usize,
}
impl CapacityError {
const fn new(attempted: usize, capacity: usize) -> Self {
Self {
attempted,
capacity,
}
}
}
impl fmt::Debug for CapacityError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CapacityError")
.field("attempted", &self.attempted)
.field("capacity", &self.capacity)
.finish()
}
}
impl fmt::Display for CapacityError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"capacity exceeded: attempted {}, capacity {}",
self.attempted, self.capacity
)
}
}
impl error::Error for CapacityError {}
fn checked_append_len<const N: usize>(
start: usize,
capacity: usize,
slices: &[&[u8]; N],
) -> Result<usize, CapacityError> {
let mut end = start;
for slice in slices {
end = end
.checked_add(slice.len())
.ok_or_else(|| CapacityError::new(usize::MAX, capacity))?;
if end > capacity {
return Err(CapacityError::new(end, capacity));
}
}
Ok(end)
}
trait RangeExt {
fn is_within(&self, len: usize) -> bool;
}
impl RangeExt for ops::Range<usize> {
fn is_within(&self, len: usize) -> bool {
self.start <= self.end && self.end <= len
}
}