use std::collections::VecDeque;
use std::fmt;
use std::iter::FusedIterator;
use std::mem::MaybeUninit;
use std::ptr;
#[repr(align(128))]
struct Block<T, const N: usize> {
slots: [MaybeUninit<T>; N],
}
impl<T, const N: usize> Block<T, N> {
fn new() -> Self {
let slots = unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() };
Self { slots }
}
}
pub(crate) struct BlockedVecDeque<T, const BLOCK_SIZE: usize = 64> {
blocks: VecDeque<Block<T, BLOCK_SIZE>>,
head_offset: usize,
tail_offset: usize,
len: usize,
}
impl<T, const BLOCK_SIZE: usize> fmt::Debug for BlockedVecDeque<T, BLOCK_SIZE> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BlockedVecDeque")
.field("len", &self.len)
.field("head_offset", &self.head_offset)
.field("tail_offset", &self.tail_offset)
.field("block_count", &self.blocks.len())
.finish()
}
}
impl<T, const BLOCK_SIZE: usize> BlockedVecDeque<T, BLOCK_SIZE> {
pub(crate) fn new() -> Self {
Self {
blocks: VecDeque::new(),
head_offset: 0,
tail_offset: 0,
len: 0,
}
}
#[inline]
pub(crate) fn len(&self) -> usize {
self.len
}
#[inline(always)]
pub(crate) fn is_empty(&self) -> bool {
self.len == 0
}
pub(crate) fn push_back(&mut self, item: T) {
if !self.blocks.is_empty() && self.tail_offset < BLOCK_SIZE {
let tail_block = self.blocks.back_mut().unwrap();
unsafe {
tail_block
.slots
.get_unchecked_mut(self.tail_offset)
.write(item);
}
self.tail_offset += 1;
} else {
let mut new_block = Block::new();
unsafe {
new_block.slots.get_unchecked_mut(0).write(item);
}
self.blocks.push_back(new_block);
if self.len == 0 {
self.head_offset = 0;
}
self.tail_offset = 1;
}
self.len += 1;
}
pub(crate) fn pop_front(&mut self) -> Option<T> {
if self.len == 0 {
return None;
}
let head_block = self.blocks.front_mut().unwrap();
let item = unsafe {
head_block
.slots
.get_unchecked(self.head_offset)
.assume_init_read()
};
self.head_offset += 1;
if self.head_offset == BLOCK_SIZE {
if self.blocks.len() > 1 {
self.blocks.pop_front();
self.head_offset = 0;
} else {
self.head_offset = 0;
self.tail_offset = 0;
}
} else if self.len == 1 {
self.head_offset = 0;
self.tail_offset = 0;
}
self.len -= 1;
Some(item)
}
pub(crate) fn push_front(&mut self, item: T) {
if self.head_offset > 0 {
self.head_offset -= 1;
let head_block = self.blocks.front_mut().unwrap();
unsafe {
head_block
.slots
.get_unchecked_mut(self.head_offset)
.write(item);
}
} else if self.len == 0 {
if self.blocks.is_empty() {
self.blocks.push_back(Block::new());
}
self.head_offset = 0;
self.tail_offset = 1;
let head_block = self.blocks.front_mut().unwrap();
unsafe {
head_block.slots.get_unchecked_mut(0).write(item);
}
} else {
let mut new_block = Block::new();
self.head_offset = BLOCK_SIZE - 1;
unsafe {
new_block
.slots
.get_unchecked_mut(self.head_offset)
.write(item);
}
self.blocks.push_front(new_block);
}
self.len += 1;
}
pub(crate) fn pop_back(&mut self) -> Option<T> {
if self.len == 0 {
return None;
}
let item;
if self.tail_offset > 0 {
self.tail_offset -= 1;
let tail_block = self.blocks.back_mut().unwrap();
item = unsafe {
tail_block
.slots
.get_unchecked(self.tail_offset)
.assume_init_read()
};
} else {
if self.blocks.len() > 1 {
self.blocks.pop_back();
self.tail_offset = BLOCK_SIZE - 1;
let new_tail = self.blocks.back_mut().unwrap();
item = unsafe {
new_tail
.slots
.get_unchecked(self.tail_offset)
.assume_init_read()
};
} else {
return None;
}
}
self.len -= 1;
if self.len == 0 {
self.head_offset = 0;
self.tail_offset = 0;
}
Some(item)
}
pub(crate) fn get(&self, index: usize) -> Option<&T> {
if index >= self.len {
return None;
}
let pos = self.head_offset + index;
let block_idx = pos / BLOCK_SIZE;
let offset = pos % BLOCK_SIZE;
let block = self.blocks.get(block_idx)?;
unsafe { Some(block.slots.get_unchecked(offset).assume_init_ref()) }
}
pub(crate) fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index >= self.len {
return None;
}
let pos = self.head_offset + index;
let block_idx = pos / BLOCK_SIZE;
let offset = pos % BLOCK_SIZE;
let block = self.blocks.get_mut(block_idx)?;
unsafe { Some(block.slots.get_unchecked_mut(offset).assume_init_mut()) }
}
pub(crate) fn clear(&mut self) {
while self.pop_front().is_some() {}
self.blocks.clear();
self.head_offset = 0;
self.tail_offset = 0;
self.len = 0;
}
pub(crate) fn shrink_to_fit(&mut self) {
self.blocks.shrink_to_fit();
}
pub(crate) fn iter(&self) -> Iter<'_, T, BLOCK_SIZE> {
Iter {
deque: self,
block_idx: 0,
offset: self.head_offset,
remaining: self.len,
}
}
pub(crate) fn iter_mut(&mut self) -> IterMut<'_, T, BLOCK_SIZE> {
IterMut {
block_iter: self.blocks.iter_mut(),
current_block_ptr: ptr::null_mut(),
block_offset: self.head_offset,
remaining: self.len,
_marker: std::marker::PhantomData,
}
}
pub(crate) fn drain(&mut self) -> Drain<'_, T, BLOCK_SIZE> {
Drain { deque: self }
}
pub(crate) fn remove_item(&mut self, item_to_remove: T) -> bool
where
T: PartialEq,
{
if self.is_empty() {
return false;
}
let original_len = self.len();
let mut temp_items = Vec::with_capacity(original_len.saturating_sub(1));
let mut found = false;
while let Some(item) = self.pop_front() {
if !found && item == item_to_remove {
found = true;
} else {
temp_items.push(item);
}
}
for item in temp_items {
self.push_back(item);
}
found
}
}
impl<T, const B: usize> Drop for BlockedVecDeque<T, B> {
fn drop(&mut self) {
self.clear();
}
}
pub(crate) struct Iter<'a, T, const B: usize> {
deque: &'a BlockedVecDeque<T, B>,
block_idx: usize,
offset: usize,
remaining: usize,
}
impl<'a, T, const B: usize> Iterator for Iter<'a, T, B> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.remaining == 0 {
return None;
}
let block = &self.deque.blocks[self.block_idx];
let item = unsafe { block.slots.get_unchecked(self.offset).assume_init_ref() };
self.offset += 1;
if self.offset == B {
self.offset = 0;
self.block_idx += 1;
}
self.remaining -= 1;
Some(item)
}
}
pub(crate) struct IterMut<'a, T, const B: usize> {
block_iter: std::collections::vec_deque::IterMut<'a, Block<T, B>>,
current_block_ptr: *mut Block<T, B>,
block_offset: usize,
remaining: usize,
_marker: std::marker::PhantomData<&'a mut T>,
}
impl<'a, T, const B: usize> Iterator for IterMut<'a, T, B> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
if self.remaining == 0 {
return None;
}
if self.current_block_ptr.is_null() {
match self.block_iter.next() {
Some(block) => {
self.current_block_ptr = block as *mut _;
}
None => return None,
}
}
let block = unsafe { &mut *self.current_block_ptr };
let item = unsafe {
block
.slots
.get_unchecked_mut(self.block_offset)
.assume_init_mut()
};
self.block_offset += 1;
self.remaining -= 1;
if self.block_offset == B {
self.block_offset = 0;
self.current_block_ptr = ptr::null_mut();
}
Some(item)
}
}
pub(crate) struct Drain<'a, T, const B: usize> {
deque: &'a mut BlockedVecDeque<T, B>,
}
impl<'a, T, const B: usize> Iterator for Drain<'a, T, B> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.deque.pop_front()
}
}
impl<'a, T, const B: usize> Drop for Drain<'a, T, B> {
fn drop(&mut self) {
self.deque.clear();
}
}
impl<'a, T, const B: usize> FusedIterator for Drain<'a, T, B> {}