2023-10-31 16:12:40 -06:00

108 lines
2.8 KiB
Rust

use core::iter::*;
pub const QUEUE_SIZE: usize = 64;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum QueueError {
NoSpace,
}
pub type Result<T> = core::result::Result<T, QueueError>;
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Queue<T> {
inner: [Option<T>; QUEUE_SIZE],
/// The index of the first item in the queue.
queue_start: usize,
/// The length of the queue.
queue_len: usize,
}
impl<T: Copy> Queue<T> {
pub const fn new() -> Queue<T> {
Queue {
inner: [None; QUEUE_SIZE],
queue_start: 0,
queue_len: 0,
}
}
}
impl<T> Queue<T> {
/// Accessor method for the length of the queue.
pub fn len(&self) -> usize {
self.queue_len
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Returns how many items can currently be added to the queue.
pub fn space_remaining(&self) -> usize {
self.inner.len() - self.len()
}
/// Returns the index of the last item in the queue.
fn queue_end(&self) -> usize {
(self.queue_start + self.queue_len - 1) % self.inner.len()
}
/// Removes an item from the front of the queue.
pub fn pop_front(&mut self) -> Option<T> {
let item = self.inner[self.queue_start].take();
if item.is_some() {
self.queue_start += 1;
self.queue_start %= self.inner.len();
self.queue_len -= 1;
}
item
}
/// Adds an item to the front of the queue.
pub fn push_front(&mut self, value: T) -> Result<()> {
if self.space_remaining() == 0 {
return Err(QueueError::NoSpace);
}
if self.queue_start == 0 {
self.queue_start = self.inner.len() - 1;
} else {
self.queue_start -= 1;
}
self.inner[self.queue_start] = Some(value);
self.queue_len += 1;
Ok(())
}
/// Removes an item from the end of the queue.
pub fn pop_back(&mut self) -> Option<T> {
let item = self.inner[self.queue_start].take();
if item.is_some() {
self.queue_len -= 1;
}
item
}
/// Adds an item to the end of the queue.
pub fn push_back(&mut self, value: T) -> Result<()> {
if self.space_remaining() == 0 {
return Err(QueueError::NoSpace);
}
self.queue_len += 1;
self.inner[self.queue_end()] = Some(value);
Ok(())
}
}
impl<T> Iterator for Queue<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.pop_front()
}
}
impl<T> DoubleEndedIterator for Queue<T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.pop_back()
}
}
impl<T> ExactSizeIterator for Queue<T> {
fn len(&self) -> usize {
self.len()
}
}