use std::{
marker, mem,
num::NonZero,
ops,
slice::{from_raw_parts, from_raw_parts_mut},
str,
};
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::{
Batch, Copy, Exclusive, Indexed, IndexedMut, Linked, LinkedMut, 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()
}
}
#[derive(Debug)]
#[repr(transparent)]
pub struct Utf8<O: buffer::raw::Source> {
owner: O,
}
impl<O: buffer::raw::Source> Utf8<O> {
pub fn try_new(owner: O) -> Result<Self, str::Utf8Error> {
str::from_utf8(owner.as_ref())?;
Ok(Self { owner })
}
pub unsafe fn new(owner: O) -> Self {
Self { owner }
}
pub fn as_str(&self) -> &str {
unsafe { str::from_utf8_unchecked(self.owner.as_ref()) }
}
pub fn as_bytes(&self) -> &[u8] {
self.owner.as_ref()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn len(&self) -> usize {
self.owner.as_ref().len()
}
}
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;
type Output: Assemble<T>;
fn owners(self) -> impl Iterator<Item = Self::Item> + Total;
fn reject(self, error: crate::alloc::Error) -> Self::Error;
}
pub trait Assemble<T: buffer::raw::Segment>: Sized {
fn finish<S: Sequence<T, Output = Self>>(input: segments::Built<T, S>) -> Self;
}
pub trait Total {
fn count(&self) -> segments::Count;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn len(&self) -> usize;
fn resident(&self) -> usize;
}
impl<I, M: Total> Total for buffer::raw::Batch<I, M> {
fn count(&self) -> segments::Count {
self.total.count()
}
fn len(&self) -> usize {
self.total.len()
}
fn resident(&self) -> usize {
self.total.resident()
}
}
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
}
}
#[derive(Debug)]
#[repr(transparent)]
pub struct Text<'d> {
text: buffer::raw::Utf8<resident::Exact<'d>>,
}
impl<'d> Text<'d> {
pub unsafe fn from_utf8(owner: resident::Exact<'d>) -> Self {
Self {
text: unsafe { buffer::raw::Utf8::new(owner) },
}
}
pub fn try_clone(&self) -> Result<Self, rc::Error> {
Ok(unsafe { Self::from_utf8(self.text.owner.try_clone()?) })
}
}
const _: () = assert!(size_of::<Text<'static>>() == size_of::<usize>());
impl<'d> ops::Deref for Text<'d> {
type Target = buffer::raw::Utf8<resident::Exact<'d>>;
fn deref(&self) -> &Self::Target {
&self.text
}
}
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>) -> pool::Complete<'a, L> {
unsafe { pool::Complete::new(self.target, len) }
}
}
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, Growth, Header, Heap, Policy, Rc, Space, Token, 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(in crate::buffer) 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();
}
}