use std::{
marker, mem,
num::NonZero,
slice::{from_raw_parts, from_raw_parts_mut},
};
use crate::{
base::num,
buffer,
buffer::{
bytes::bounded,
pool::{self, owners, state},
resident, segments,
storage::provided,
},
mem::rc,
};
mod slices;
pub use slices::Slices;
mod store;
pub use store::Store;
mod segment;
pub use segment::Segment;
mod scatter;
pub use scatter::Scatter;
pub(in crate::buffer) use slices::{Exclusive, Prefix, SliceExt};
pub unsafe trait Consume: AsRef<[u8]> {
fn consume<const MAX: u32>(prefix: Consumed<'_, '_, Self, MAX>);
}
unsafe impl Consume for &mut [u8] {
fn consume<const MAX: u32>(prefix: Consumed<'_, '_, Self, MAX>) {
let (target, end) = prefix.into_parts();
let bytes = mem::take(target);
*target = unsafe { bytes.get_unchecked_mut(end.count().get() as usize..) };
}
}
unsafe impl<S: ?Sized> Consume for buffer::View<'_, S> {
fn consume<const MAX: u32>(prefix: Consumed<'_, '_, Self, MAX>) {
let (view, end) = prefix.into_parts();
view.bytes = unsafe { view.bytes.get_unchecked(end.count().get() as usize..) };
}
}
pub unsafe trait Retain: Sized {
fn try_retain(&self) -> Result<Self, rc::Error>;
}
unsafe impl<T: Retain> Retain for Option<T> {
fn try_retain(&self) -> Result<Self, rc::Error> {
self.as_ref().map(T::try_retain).transpose()
}
}
pub unsafe fn utf8<O: Source>(owner: O) -> buffer::storage::Str<O> {
unsafe { buffer::storage::Str::new(owner) }
}
pub unsafe trait Convert<T> {
fn into(self) -> T;
}
unsafe impl<T> Convert<T> for T {
fn into(self) -> T {
self
}
}
pub trait Unary<T> {
fn item(&self) -> &segments::Item<T>;
}
pub unsafe trait Sequence<T: buffer::raw::Segment>: Sized + Total {
type Item;
type Error;
fn owners(self) -> (impl Iterator<Item = Self::Item>, impl Total);
fn reject(self, error: crate::alloc::Error) -> Self::Error;
}
pub trait Total {
fn count(&self) -> segments::Count;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn len(&self) -> usize;
fn resident(&self) -> usize;
}
pub unsafe trait Chunks {
type Cursor<'data>: Scatter<'data>
where
Self: 'data;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn len(&self) -> usize;
fn start(&self) -> Self::Cursor<'_>;
fn cursor(&self, offset: usize) -> Option<Self::Cursor<'_>> {
Scatter::seek(self.start(), offset)
}
}
pub unsafe trait Input<T> {
fn bytes(&self) -> &[u8];
fn into_item(self) -> (T, impl for<'a> FnOnce(&'a mut T) -> &'a mut [u8]);
}
pub trait Fixed<T> {
fn resident(&self) -> NonZero<u32>;
unsafe fn project<'a, 'id>(&'a self, item: &'a mut T, limit: Limit<'id>)
-> Projection<'a, 'id>;
unsafe fn insert<'d>(
vacant: provided::Vacant<'d, T, (), &'d Self>,
item: T,
) -> provided::Unique<'d>
where
Self: Sized,
{
let context = vacant.context();
vacant.insert_with(item, |item, limit| {
unsafe { context.project(item, limit) }
})
}
}
pub unsafe trait Arenas: Unpin {
type Roots<'d>: 'd
where
Self: 'd;
unsafe fn enter(&mut self) -> (Self::Roots<'_>, impl FnOnce() + '_);
}
unsafe impl<A: Arenas, B: Arenas> Arenas for (A, B) {
type Roots<'d>
= (A::Roots<'d>, B::Roots<'d>)
where
Self: 'd;
unsafe fn enter(&mut self) -> (Self::Roots<'_>, impl FnOnce() + '_) {
let (first, finish) = unsafe { self.0.enter() };
let (second, end) = unsafe { self.1.enter() };
((first, second), move || {
end();
finish();
})
}
}
#[repr(transparent)]
pub struct Projection<'a, 'id> {
bytes: &'a mut [u8],
operation: marker::PhantomData<fn(&'id mut ()) -> &'id mut ()>,
}
impl<'a> Projection<'a, '_> {
pub(in crate::buffer) const fn into_inner(self) -> &'a mut [u8] {
self.bytes
}
}
pub type Text<'d> = buffer::storage::Str<resident::Exact<'d>>;
pub struct Output<'a, L = pool::Layout> {
target: &'a mut pool::Span<owners::Plain<L>, pool::Owned, state::Initialized>,
}
impl<'a, L> Output<'a, L> {
pub(in crate::buffer) const fn new(
target: &'a mut pool::Span<owners::Plain<L>, pool::Owned, state::Initialized>,
) -> Self {
Self { target }
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn len(&self) -> usize {
self.target.capacity().get() as usize - self.target.len()
}
pub fn as_mut_slice(&mut self) -> &mut [u8] {
let (data, start) = buffer::raw::Prefix::prefix(self.target);
unsafe { range_mut(data.cast(), start as usize, self.len()) }
}
pub unsafe fn complete(self, len: NonZero<usize>) {
*Exclusive::len_mut(self.target) += len.get() as u32;
}
}
const _: () = assert!(size_of::<Output<'_>>() == size_of::<usize>());
pub unsafe trait Project<T: ?Sized>: AsRef<[u8]> {
fn as_inner(&self) -> &T;
unsafe fn as_inner_mut(&mut self) -> &mut T;
}
unsafe impl<T: AsRef<[u8]>> Project<T> for bounded::Value<T> {
fn as_inner(&self) -> &T {
&self.0
}
unsafe fn as_inner_mut(&mut self) -> &mut T {
&mut self.0
}
}
pub unsafe trait Source: AsRef<[u8]> {}
unsafe impl<T: buffer::raw::Consume> Source for T {}
pub unsafe trait Mutable: Source + AsMut<[u8]> {}
pub unsafe trait Split: Mutable {}
pub unsafe trait Freeze: Source + Sized {
type Output: Source;
fn freeze(self) -> Self::Output;
}
pub unsafe trait Initializer {
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
unsafe fn initialize(&self, target: *mut mem::MaybeUninit<u8>);
}
pub(in crate::buffer) use store::{Backing, Debit, Header, Heap, Policy, Rc, Unique};
mod length;
pub use length::Length;
mod limit;
pub use limit::Limit;
mod consumed;
pub use consumed::Consumed;
pub(in crate::buffer) use consumed::Selection;
mod slice;
pub use slice::Slice;
#[repr(transparent)]
pub struct Chunk<'data, const MAX: usize = { usize::MAX }> {
bytes: &'data [u8],
}
pub(in crate::buffer) unsafe fn range<'a>(
pointer: *const u8,
start: usize,
len: usize,
) -> &'a [u8] {
unsafe { from_raw_parts(pointer.add(start), len) }
}
pub(in crate::buffer) unsafe fn range_mut<'a>(
pointer: *mut u8,
start: usize,
len: usize,
) -> &'a mut [u8] {
unsafe { from_raw_parts_mut(pointer.add(start), len) }
}
impl<'data, const MAX: usize> Chunk<'data, MAX> {
pub unsafe fn new(bytes: &'data [u8]) -> Self {
Self { bytes }
}
pub const fn bytes(&self) -> &'data [u8] {
self.bytes
}
pub const fn len(&self) -> num::bounded::NonZeroUsize<1, MAX> {
unsafe { num::bounded::raw::nonzero_usize(self.bytes.len()) }
}
}
const _: () = {
assert!(mem::size_of::<Chunk<'static>>() == mem::size_of::<&[u8]>());
assert!(mem::size_of::<Option<Chunk<'static>>>() == mem::size_of::<&[u8]>());
};
pub unsafe fn copy_slices<'a>(sources: impl IntoIterator<Item = &'a [u8]>, target: *mut u8) {
let mut offset = 0;
for source in sources {
unsafe { source.copy_to(target.add(offset)) };
offset += source.len();
}
}