macro_rules! do_get {
($block:ident, $metadata:expr, $ptr:expr, $slice:ident, $($ref:tt)*) => {
$block {
data: {
let pointer = unsafe { $ptr.add($metadata.begin) };
unsafe { $($ref)* *ptr::$slice(pointer, $metadata.len) }
},
misc: $($ref)* $metadata.misc,
range: $metadata.begin..$metadata.begin.wrapping_add($metadata.len)
}
}
}
macro_rules! get {
($metadata:expr, $ptr:expr) => {
do_get!(BlockRef, $metadata, $ptr, slice_from_raw_parts, &)
}
}
macro_rules! get_mut {
($metadata:expr, $ptr:expr) => {
do_get!(BlockMut, $metadata, $ptr, slice_from_raw_parts_mut, &mut)
}
}
mod block;
mod blocks_deque_builder;
mod metadata;
#[cfg(test)]
mod tests;
use crate::misc::Deque;
pub use block::Block;
pub use blocks_deque_builder::BlocksDequeBuilder;
use core::ptr;
type BlockRef<'bq, D, M> = Block<&'bq [D], &'bq M>;
type BlockMut<'bq, D, M> = Block<&'bq mut [D], &'bq mut M>;
#[derive(Debug)]
pub enum BlocksDequeError {
#[doc = doc_single_elem_cap_overflow!()]
PushOverflow,
#[doc = doc_reserve_overflow!()]
ReserveOverflow,
#[doc = doc_reserve_overflow!()]
WithCapacityOverflow,
}
#[derive(Debug)]
pub struct BlocksDeque<D, M> {
data: Deque<D>,
metadata: Deque<metadata::Metadata<M>>,
}
impl<D, M> BlocksDeque<D, M> {
#[inline]
pub const fn new() -> Self {
Self { data: Deque::new(), metadata: Deque::new() }
}
#[inline]
pub fn with_capacity(blocks: usize, elements: usize) -> crate::Result<Self> {
Ok(Self {
data: Deque::with_capacity(elements)
.map_err(|_err| BlocksDequeError::WithCapacityOverflow)?,
metadata: Deque::with_capacity(blocks)
.map_err(|_err| BlocksDequeError::WithCapacityOverflow)?,
})
}
#[inline]
pub fn with_exact_capacity(blocks: usize, elements: usize) -> crate::Result<Self> {
Ok(Self {
data: Deque::with_exact_capacity(elements)
.map_err(|_err| BlocksDequeError::WithCapacityOverflow)?,
metadata: Deque::with_exact_capacity(blocks)
.map_err(|_err| BlocksDequeError::WithCapacityOverflow)?,
})
}
#[inline]
pub fn as_slices(&self) -> (&[D], &[D]) {
self.data.as_slices()
}
#[inline]
pub fn blocks_capacity(&self) -> usize {
self.metadata.capacity()
}
#[inline]
pub fn blocks_len(&self) -> usize {
self.metadata.len()
}
#[inline]
pub fn builder_back(&mut self) -> BlocksDequeBuilder<'_, D, M, true> {
BlocksDequeBuilder::new(self)
}
#[inline]
pub fn builder_front(&mut self) -> BlocksDequeBuilder<'_, D, M, false> {
BlocksDequeBuilder::new(self)
}
#[inline]
pub fn clear(&mut self) {
let Self { data, metadata } = self;
data.clear();
metadata.clear();
}
#[inline]
pub fn elements_capacity(&self) -> usize {
self.data.capacity()
}
#[inline]
pub fn elements_len(&self) -> usize {
self.data.len()
}
#[inline]
pub fn get(&self, idx: usize) -> Option<BlockRef<'_, D, M>> {
let metadata = self.metadata.get(idx)?;
Some(get!(metadata, self.data.as_ptr()))
}
#[inline]
pub fn get_mut(&mut self, idx: usize) -> Option<BlockMut<'_, D, M>> {
let metadata = self.metadata.get_mut(idx)?;
Some(get_mut!(metadata, self.data.as_ptr_mut()))
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = BlockRef<'_, D, M>> {
self.metadata.iter().map(|metadata| get!(metadata, self.data.as_ptr()))
}
#[inline]
pub fn iter_mut(&mut self) -> impl Iterator<Item = BlockMut<'_, D, M>> {
let Self { data, metadata } = self;
metadata
.iter_mut()
.map(move |elem| do_get!(BlockMut, elem, data.as_ptr_mut(), slice_from_raw_parts_mut, &mut))
}
#[inline]
pub fn pop_back(&mut self) -> Option<M> {
let metadata = self.metadata.pop_back()?;
self.data.truncate_back(self.elements_len().wrapping_sub(metadata.len));
Some(metadata.misc)
}
#[inline]
pub fn pop_front(&mut self) -> Option<M> {
let metadata = self.metadata.pop_front()?;
self.data.truncate_front(self.elements_len().wrapping_sub(metadata.len));
Some(metadata.misc)
}
#[inline]
pub fn push_back_from_copyable_data<'data, I>(&mut self, data: I, misc: M) -> crate::Result<()>
where
D: Copy + 'data,
I: IntoIterator<Item = &'data [D]>,
I::IntoIter: Clone,
{
let total_data_len = self
.data
.extend_back_from_copyable_slices(data)
.map_err(|_err| BlocksDequeError::PushOverflow)?;
let begin = self.data.tail().wrapping_sub(total_data_len);
self
.metadata
.push_back(metadata::Metadata { begin, len: total_data_len, misc })
.map_err(|_err| BlocksDequeError::PushOverflow)?;
Ok(())
}
#[inline]
pub fn push_front_from_coyable_data<'data, I>(&mut self, data: I, misc: M) -> crate::Result<()>
where
D: Copy + 'data,
I: IntoIterator<Item = &'data [D]>,
I::IntoIter: Clone,
{
let (total_data_len, head_shift) = self
.data
.extend_front_from_copyable_slices(data)
.map_err(|_err| BlocksDequeError::PushOverflow)?;
self
.metadata
.push_front(metadata::Metadata { begin: self.data.head(), len: total_data_len, misc })
.map_err(|_err| BlocksDequeError::PushOverflow)?;
self.adjust_metadata(head_shift, 1);
Ok(())
}
#[inline(always)]
pub fn reserve_front(&mut self, blocks: usize, elements: usize) -> crate::Result<()> {
let _ = self.metadata.reserve_front(blocks).map_err(|_er| BlocksDequeError::ReserveOverflow)?;
let n = self.data.reserve_front(elements).map_err(|_err| BlocksDequeError::ReserveOverflow)?;
self.adjust_metadata(n, 0);
Ok(())
}
#[inline]
fn adjust_metadata(&mut self, head_shift: usize, skip: usize) {
if head_shift > 0 {
for metadata in self.metadata.iter_mut().skip(skip) {
metadata.begin = metadata.begin.wrapping_add(head_shift);
}
}
}
}
impl<D, M> Default for BlocksDeque<D, M> {
#[inline]
fn default() -> Self {
Self::new()
}
}