use alloc::vec::Vec;
pub(crate) const INLINE: usize = 32;
#[derive(Clone, Debug)]
pub(crate) struct RunBuffer<T> {
inline: [T; INLINE],
len: usize,
spill: Vec<T>,
}
impl<T: Copy + Default> RunBuffer<T> {
pub(crate) fn new() -> Self {
RunBuffer {
inline: [T::default(); INLINE],
len: 0,
spill: Vec::new(),
}
}
#[inline]
fn spilled(&self) -> bool {
self.spill.capacity() != 0
}
#[inline]
pub(crate) fn len(&self) -> usize {
if self.spilled() {
self.spill.len()
} else {
self.len
}
}
#[inline]
pub(crate) fn push(&mut self, item: T) {
if self.spilled() {
self.spill.push(item);
} else if let Some(slot) = self.inline.get_mut(self.len) {
*slot = item;
self.len += 1;
} else {
let mut spill = Vec::with_capacity(INLINE * 2);
spill.extend_from_slice(&self.inline);
spill.push(item);
self.spill = spill;
}
}
#[inline]
pub(crate) fn try_push(&mut self, item: T) -> bool {
if self.spilled() {
if self.spill.len() == self.spill.capacity() {
return false;
}
self.spill.push(item);
} else if let Some(slot) = self.inline.get_mut(self.len) {
*slot = item;
self.len += 1;
} else {
return false;
}
true
}
#[inline]
pub(crate) fn compact_front(&mut self, n: usize) {
if n == 0 {
return;
}
if self.spilled() {
let len = self.spill.len();
self.spill.copy_within(n.., 0);
self.spill.truncate(len - n);
} else {
self.inline.copy_within(n..self.len, 0);
self.len -= n;
}
}
#[inline]
pub(crate) fn clear(&mut self) {
self.len = 0;
self.spill.clear();
}
#[inline]
pub(crate) fn get(&self, i: usize) -> Option<&T> {
self.as_slice().get(i)
}
#[inline]
pub(crate) fn as_slice(&self) -> &[T] {
if self.spilled() {
&self.spill
} else {
self.inline.get(..self.len).unwrap_or(&[])
}
}
#[inline]
pub(crate) fn as_mut_slice(&mut self) -> &mut [T] {
if self.spilled() {
&mut self.spill
} else {
self.inline.get_mut(..self.len).unwrap_or(&mut [])
}
}
}