use core::ops::{Deref, DerefMut, Index, IndexMut};
pub mod circular;
pub trait Collection {
fn with_capacity(cap: usize) -> Self;
}
pub trait Queue {
type Item;
fn enque(&mut self, item: Self::Item);
fn deque(&mut self) -> Option<Self::Item>;
fn len(&self) -> usize;
fn cap(&self) -> usize;
fn get(&self, idx: usize) -> Option<&Self::Item>;
fn get_mut(&mut self, idx: usize) -> Option<&mut Self::Item>;
#[inline]
fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
fn is_full(&self) -> bool {
self.len() == self.cap()
}
fn is_inline(&self) -> bool;
#[inline]
fn enque_and_deque_overflow(&mut self, item: Self::Item) -> Option<Self::Item> {
if self.is_full() {
let oldest = self.deque();
self.enque(item);
oldest
} else {
self.enque(item);
None
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Change<T> {
Push(Option<T>),
Swap(Option<T>),
}
impl<T> Change<T> {
pub fn as_ref(&self) -> Change<&T> {
match self {
Self::Push(v) => Change::Push(v.as_ref()),
Self::Swap(v) => Change::Swap(v.as_ref()),
}
}
pub fn outdated(self) -> Option<T> {
match self {
Self::Push(v) => v,
Self::Swap(v) => v,
}
}
pub fn is_new_period(&self) -> bool {
matches!(self, Self::Push(_))
}
fn as_push(&self) -> Option<&T> {
if let Self::Push(v) = self {
v.as_ref()
} else {
None
}
}
fn as_swap(&self) -> Option<&T> {
if let Self::Swap(v) = self {
v.as_ref()
} else {
None
}
}
}
#[derive(Debug, Clone)]
pub struct Tumbling<Q: Queue>(Q, Change<Q::Item>);
impl<Q> Tumbling<Q>
where
Q: Queue,
{
pub(crate) fn new(queue: Q) -> Self {
Self(queue, Change::Push(None))
}
pub fn as_view<'a>(&'a self) -> View<'a, dyn Queue<Item = Q::Item> + 'a> {
View {
queue: &self.0,
change: &self.1,
}
}
pub fn as_queue_ref(&self) -> QueueRef<'_, Q::Item> {
QueueRef(self.as_view())
}
pub fn as_view_mut<'a>(&'a mut self) -> ViewMut<'a, dyn Queue<Item = Q::Item> + 'a> {
ViewMut {
queue: &mut self.0,
change: &mut self.1,
}
}
pub fn as_queue_mut(&mut self) -> QueueMut<'_, Q::Item> {
QueueMut(self.as_view_mut())
}
}
impl<Q> Deref for Tumbling<Q>
where
Q: Queue,
{
type Target = Q;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct View<'a, Q: Queue + ?Sized> {
queue: &'a Q,
change: &'a Change<Q::Item>,
}
impl<'a, Q: Queue + ?Sized> Clone for View<'a, Q> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, Q: Queue + ?Sized> Copy for View<'a, Q> {}
impl<'a, Q: Queue + ?Sized> View<'a, Q> {
#[inline]
pub fn change(&self) -> Change<&Q::Item> {
self.change.as_ref()
}
}
impl<'a, Q> Deref for View<'a, Q>
where
Q: Queue + ?Sized,
{
type Target = Q;
fn deref(&self) -> &Self::Target {
self.queue
}
}
impl<'a, Q> Index<usize> for View<'a, Q>
where
Q: Queue + ?Sized,
{
type Output = Q::Item;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
self.queue.get(index).expect("index out of range")
}
}
pub struct QueueRef<'a, T>(View<'a, dyn Queue<Item = T> + 'a>);
impl<'a, T> Clone for QueueRef<'a, T> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, T> Copy for QueueRef<'a, T> {}
impl<'a, T> Deref for QueueRef<'a, T> {
type Target = View<'a, dyn Queue<Item = T> + 'a>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct ViewMut<'a, Q: Queue + ?Sized> {
queue: &'a mut Q,
change: &'a mut Change<Q::Item>,
}
impl<'a, Q: Queue + ?Sized> ViewMut<'a, Q> {
#[inline]
pub fn push(&mut self, item: Q::Item) -> Option<&Q::Item> {
*self.change = Change::Push(self.queue.enque_and_deque_overflow(item));
self.change.as_push()
}
#[inline]
pub fn swap(&mut self, mut item: Q::Item) -> Option<&Q::Item> {
if let Some(head) = self.queue.get_mut(0) {
core::mem::swap(head, &mut item);
}
*self.change = Change::Swap(Some(item));
self.change.as_swap()
}
#[inline]
pub fn change(&self) -> Change<&Q::Item> {
self.change.as_ref()
}
}
impl<'a, Q> Deref for ViewMut<'a, Q>
where
Q: Queue + ?Sized,
{
type Target = Q;
fn deref(&self) -> &Self::Target {
self.queue
}
}
impl<'a, Q> DerefMut for ViewMut<'a, Q>
where
Q: Queue + ?Sized,
{
fn deref_mut(&mut self) -> &mut Self::Target {
self.queue
}
}
impl<'a, Q> Index<usize> for ViewMut<'a, Q>
where
Q: Queue + ?Sized,
{
type Output = Q::Item;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
self.queue.get(index).expect("index out of range")
}
}
impl<'a, Q> IndexMut<usize> for ViewMut<'a, Q>
where
Q: Queue,
{
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.queue.get_mut(index).expect("index out of range")
}
}
pub struct QueueMut<'a, T>(ViewMut<'a, dyn Queue<Item = T> + 'a>);
impl<'a, T> QueueMut<'a, T> {
pub fn as_queue_ref(&self) -> QueueRef<T> {
QueueRef(View {
queue: self.queue,
change: self.change,
})
}
pub fn into_queue_ref(self) -> QueueRef<'a, T> {
QueueRef(View {
queue: self.0.queue,
change: self.0.change,
})
}
}
impl<'a, T> Deref for QueueMut<'a, T> {
type Target = ViewMut<'a, dyn Queue<Item = T> + 'a>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<'a, T> DerefMut for QueueMut<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}