use std::mem::size_of;
use std::mem::take;
use std::ops::Deref;
use std::ops::DerefMut;
use std::ops::Index;
use std::ops::IndexMut;
use crate::RingIter;
use crate::RingIterMut;
#[derive(Clone, Debug, PartialEq)]
pub struct RingBuf<T> {
data: Box<[T]>,
next: usize,
}
impl<T> RingBuf<T>
where
T: Default,
{
pub fn new(len: usize) -> Self {
let mut vec = Vec::with_capacity(len);
vec.resize_with(len, Default::default);
Self::from_vec(vec)
}
pub fn pop_front(&mut self) -> T {
let idx = self.front_idx();
self.next = if self.next == 0 {
self.len() - 1
} else {
self.next - 1
};
#[cfg(debug_assertions)]
let front = take(self.data.get_mut(idx).unwrap());
#[cfg(not(debug_assertions))]
let front = take(unsafe { self.data.get_unchecked_mut(idx) });
front
}
pub fn into_boxed_slice(self) -> Box<[T]> {
self.data
}
}
#[allow(clippy::len_without_is_empty)]
impl<T> RingBuf<T> {
pub fn from_vec(vec: Vec<T>) -> Self {
assert!(!vec.is_empty());
Self {
data: vec.into_boxed_slice(),
next: 0,
}
}
#[inline]
pub const fn len(&self) -> usize {
self.data.len()
}
#[inline]
pub fn front(&self) -> &T {
let idx = self.front_idx();
#[cfg(debug_assertions)]
let front = self.data.get(idx).unwrap();
#[cfg(not(debug_assertions))]
let front = unsafe { self.data.get_unchecked(idx) };
front
}
#[inline]
pub fn front_mut(&mut self) -> &mut T {
let idx = self.front_idx();
#[cfg(debug_assertions)]
let front = self.data.get_mut(idx).unwrap();
#[cfg(not(debug_assertions))]
let front = unsafe { self.data.get_unchecked_mut(idx) };
front
}
#[inline]
pub fn front_idx(&self) -> usize {
if self.next == 0 {
self.len() - 1
} else {
self.next - 1
}
}
#[inline]
pub fn back(&self) -> &T {
let idx = self.back_idx();
#[cfg(debug_assertions)]
let back = self.data.get(idx).unwrap();
#[cfg(not(debug_assertions))]
let back = unsafe { self.data.get_unchecked(idx) };
back
}
#[inline]
pub fn back_mut(&mut self) -> &mut T {
let idx = self.back_idx();
#[cfg(debug_assertions)]
let back = self.data.get_mut(idx).unwrap();
#[cfg(not(debug_assertions))]
let back = unsafe { self.data.get_unchecked_mut(idx) };
back
}
#[inline]
pub fn back_idx(&self) -> usize {
self.next
}
#[inline]
pub fn push_front(&mut self, elem: T) {
let next = self.next;
let len = self.data.len();
debug_assert!(next < len, "next: {}, len: {}", next, len);
#[cfg(debug_assertions)]
{
*self.data.get_mut(next).unwrap() = elem;
}
#[cfg(not(debug_assertions))]
unsafe {
*self.data.get_unchecked_mut(next) = elem;
}
self.next = (next + 1) % len;
}
#[inline]
pub const fn iter(&self) -> RingIter<'_, T> {
RingIter::new(&self.data, self.next)
}
#[inline]
pub fn iter_mut(&mut self) -> RingIterMut<'_, T> {
assert_ne!(
size_of::<T>(),
0,
"Mutable iterators are not supported on ring buffers over zero sized types"
);
RingIterMut::new(&mut self.data, self.next)
}
}
impl<T> Deref for RingBuf<T> {
type Target = [T];
#[inline]
fn deref(&self) -> &Self::Target {
self.data.deref()
}
}
impl<T> DerefMut for RingBuf<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.data.deref_mut()
}
}
impl<T> Index<usize> for RingBuf<T> {
type Output = T;
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
let idx = (self.back_idx() + idx) % self.len();
#[cfg(debug_assertions)]
let elem = self.data.get(idx).unwrap();
#[cfg(not(debug_assertions))]
let elem = unsafe { self.data.get_unchecked(idx) };
elem
}
}
impl<T> IndexMut<usize> for RingBuf<T> {
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
let idx = (self.back_idx() + idx) % self.len();
#[cfg(debug_assertions)]
let elem = self.data.get_mut(idx).unwrap();
#[cfg(not(debug_assertions))]
let elem = unsafe { self.data.get_unchecked_mut(idx) };
elem
}
}