use std::mem;
use crate::{
buffer,
buffer::{
segments,
segments::{
Chain, Handle, Key,
chain::{view, view::iter::Iter},
handles::{self, Occupied},
},
},
depot::arena::linked::{self, slots},
};
impl<T, H: Handle<T>> Chain<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() {
None => return,
Some(Occupied::Single(index)) => {
drop(unsafe { nodes.detached(index) });
return;
}
Some(Occupied::Multi(index)) => index,
};
let descs = handles::descriptors(handle);
let (mut desc, retired) = unsafe { descs.detached(index) }.take();
unsafe { desc.links.clear(nodes) };
retired.release();
}
}
impl<T, H: Handle<T>> Drop for Chain<T, H> {
fn drop(&mut self) {
Self::release(&self.handle, &self.key);
}
}
impl<T: buffer::raw::Segment, H: Handle<T>> Chain<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 = unsafe { handles::nodes(&self.handle).value(index) };
view::Occupied::Single(index, node)
}
handles::Occupied::Multi(index) => {
let desc = unsafe { handles::descriptors(&self.handle).value(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)
}
}