use crate::ring::PicoRing;
pub struct PicoQueue<T, const N: usize = 0> {
ring: PicoRing<T, N>,
}
impl<T, const N: usize> PicoQueue<T, N> {
pub fn new_static() -> Result<Self, String> {
Ok(Self {
ring: PicoRing::new()?,
})
}
}
impl<T> PicoQueue<T, 0> {
pub fn new(capacity: usize) -> Result<Self, String> {
Ok(Self {
ring: PicoRing::with_capacity(capacity)?,
})
}
}
impl<T, const N: usize> PicoQueue<T, N> {
#[inline]
pub fn len(&self) -> usize {
self.ring.len()
}
#[inline]
pub fn capacity(&self) -> usize {
self.ring.capacity()
}
#[inline]
pub fn reserve(&mut self, len: usize) -> Option<&mut [T]> {
if self.ring.available_space() < len {
return None;
}
self.ring.view_mut(self.ring.head(), len)
}
#[inline]
pub fn commit(&mut self, len: usize) {
self.ring.advance_head(len);
}
#[inline]
pub fn peek(&self) -> &[T] {
self.ring.readable_slice()
}
#[inline]
pub fn release(&mut self, len: usize) {
let n = len.min(self.len());
self.ring.advance_tail(n);
}
#[inline]
pub fn iter(&self) -> core::slice::Iter<'_, T> {
self.peek().iter()
}
#[inline]
pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, T> {
unsafe {
let ptr = self.ring.as_mut_ptr().add(self.ring.tail());
core::slice::from_raw_parts_mut(ptr, self.len()).iter_mut()
}
}
}
impl<T: Copy, const N: usize> PicoQueue<T, N> {
#[inline]
pub fn try_push(&mut self, item: T) -> bool {
self.ring.push(item)
}
#[inline]
pub fn try_pop(&mut self) -> Option<T> {
self.ring.pop()
}
}
impl<T: Copy> From<Vec<T>> for PicoQueue<T> {
fn from(v: Vec<T>) -> Self {
Self {
ring: PicoRing::from(v),
}
}
}
impl<T, const N: usize> core::ops::Index<usize> for PicoQueue<T, N> {
type Output = T;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
&self.peek()[index]
}
}
impl<T, const N: usize> core::ops::IndexMut<usize> for PicoQueue<T, N> {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
unsafe {
let ptr = self.ring.as_mut_ptr().add(self.ring.tail());
let slice = core::slice::from_raw_parts_mut(ptr, self.len());
&mut slice[index]
}
}
}
impl<'a, T, const N: usize> IntoIterator for &'a PicoQueue<T, N> {
type Item = &'a T;
type IntoIter = core::slice::Iter<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T, const N: usize> IntoIterator for &'a mut PicoQueue<T, N> {
type Item = &'a mut T;
type IntoIter = core::slice::IterMut<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}