use std::{marker, mem};
use crate::{
buffer,
buffer::{
segments,
segments::{
Handle, Key, Pool,
chain::{view, view::iter::Iter},
handles,
},
},
depot::arena::linked::{self, fifo::ends, slots},
};
#[derive(Debug)]
#[repr(C)]
pub struct Sequence<T, H: Handle<T> = Pool<T>> {
pub(in crate::buffer::segments) handle: H,
pub(in crate::buffer::segments) key: Key,
pub(in crate::buffer::segments) owner: marker::PhantomData<fn() -> T>,
}
struct Node<'a, T, H: Handle<T>> {
source: &'a Sequence<T, H>,
index: slots::Index,
}
struct Links<'a, T, H: Handle<T>> {
source: &'a Sequence<T, H>,
index: slots::Index,
}
unsafe impl<'a, T: 'a, H: Handle<T>> buffer::raw::Indexed<'a> for Node<'a, T, H> {
type Item = segments::Item<T>;
fn parts(self) -> (&'a slots::Store<Self::Item>, slots::Index) {
(handles::nodes(&self.source.handle), self.index)
}
}
unsafe impl<'a, T: 'a, H: Handle<T>> buffer::raw::Linked<'a> for Links<'a, T, H> {
type Item = segments::Item<T>;
type Metadata = handles::Descriptor;
fn parts(
self,
) -> (
&'a slots::Store<Self::Item>,
&'a slots::Store<Self::Metadata>,
slots::Index,
) {
(
handles::nodes(&self.source.handle),
handles::descriptors(&self.source.handle),
self.index,
)
}
fn head(metadata: &Self::Metadata) -> slots::Index {
metadata.links.head_raw()
}
}
impl<T, H: Handle<T>> Sequence<T, H> {
pub fn clear(&mut self) {
let key = mem::replace(&mut self.key, Key::EMPTY);
Self::release(&self.handle, &key);
}
fn release(handle: &H, key: &Key) {
let nodes = handles::nodes(handle);
let index = match key.state() {
handles::State::Empty => return,
handles::State::Single(index) => {
drop(unsafe { nodes.detached(index) });
return;
}
handles::State::Multi(index) => index,
};
let descs = handles::descriptors(handle);
let (mut desc, retired) = unsafe { descs.detached(index) }.take();
let mut links = unsafe { ends::Bound::new(nodes, &mut desc.links) };
links.clear();
retired.release();
}
}
impl<T, H: Handle<T>> Drop for Sequence<T, H> {
fn drop(&mut self) {
Self::release(&self.handle, &self.key);
}
}
impl<T: buffer::raw::Segment, H: Handle<T>> Sequence<T, H> {
pub(in crate::buffer::segments) fn state(&self) -> view::State<'_, T> {
if self.key.is_empty() {
return view::State::Empty;
}
match unsafe { self.occupied() } {
view::Occupied::Single(index, item) => view::State::Single(index, item),
view::Occupied::Multi(desc) => view::State::Multi(desc),
}
}
pub(in crate::buffer::segments) unsafe fn occupied(&self) -> view::Occupied<'_, T> {
match unsafe { self.key.occupied() } {
handles::Occupied::Single(index) => {
let node = buffer::raw::Indexed::get(Node {
source: self,
index,
});
view::Occupied::Single(index, node)
}
handles::Occupied::Multi(index) => {
let desc = buffer::raw::Linked::metadata(Links {
source: self,
index,
});
view::Occupied::Multi(desc)
}
}
}
pub(in crate::buffer::segments) fn totals(&self) -> (segments::Count, usize, usize) {
match self.state() {
view::State::Empty => (segments::Count::EMPTY, 0, 0),
view::State::Single(_, item) => (
segments::Count::ONE,
item.len().get(),
buffer::Residency::resident(item),
),
view::State::Multi(desc) => (
segments::Count::new(desc.count.get()),
desc.len,
desc.resident_bytes,
),
}
}
pub fn len(&self) -> usize {
match self.state() {
view::State::Empty => 0,
view::State::Single(_, item) => item.len().get(),
view::State::Multi(desc) => desc.len,
}
}
pub fn is_empty(&self) -> bool {
self.key.is_empty()
}
pub fn count(&self) -> segments::Count {
match self.state() {
view::State::Empty => segments::Count::EMPTY,
view::State::Single(_, _) => segments::Count::ONE,
view::State::Multi(desc) => segments::Count::new(desc.count.get()),
}
}
pub fn resident(&self) -> usize {
match self.state() {
view::State::Empty => 0,
view::State::Single(_, item) => buffer::Residency::resident(item),
view::State::Multi(desc) => desc.resident_bytes,
}
}
pub fn segments(&self) -> Iter<'_, T> {
let (head, left) = match self.state() {
view::State::Empty => (slots::Index::NONE, segments::Count::EMPTY),
view::State::Single(index, _) => (index, segments::Count::ONE),
view::State::Multi(desc) => (
desc.links.head_raw(),
segments::Count::new(desc.count.get()),
),
};
let cursor = unsafe { linked::Iter::new(handles::nodes(&self.handle), head) };
Iter::new(cursor, left)
}
pub fn contiguous(&self) -> Option<&[u8]> {
match self.state() {
view::State::Empty => Some(&[]),
view::State::Single(_, item) => Some(item.as_ref().as_ref()),
view::State::Multi(_) => None,
}
}
pub(in crate::buffer::segments) fn is_same(&self, other: &Self) -> bool {
self.handle.is_same(&other.handle)
}
}