use std::collections::VecDeque;
pub struct LimQ<T> {
q: VecDeque<T>,
max_len: Option<usize>
}
impl<T> LimQ<T> {
pub fn new(max_len: Option<usize>) -> Self {
assert!(!matches!(max_len, Some(0)));
let q = if let Some(max_len) = max_len {
VecDeque::with_capacity(max_len)
} else {
VecDeque::new()
};
Self { max_len, q }
}
pub fn set_max_len(&mut self, max_len: Option<usize>) {
assert!(!matches!(max_len, Some(0)));
self.max_len = max_len;
}
#[inline]
pub fn max_len(&self) -> Option<usize> {
self.max_len
}
#[inline]
pub fn len(&self) -> usize {
self.q.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.q.is_empty()
}
#[inline]
pub fn purge_overflow(&mut self) {
if let Some(max_len) = self.max_len {
while self.q.len() > max_len {
let _ = self.q.pop_front();
}
}
}
#[inline]
pub fn try_push(&mut self, n: T) -> Result<(), T> {
if let Some(max_len) = self.max_len {
if self.q.len() < max_len {
self.q.push_back(n);
Ok(())
} else {
Err(n)
}
} else {
self.q.push_back(n);
Ok(())
}
}
#[inline]
pub fn force_push(&mut self, n: T) {
if let Some(max_len) = self.max_len {
while self.q.len() > (max_len - 1) {
let _ = self.q.pop_front();
}
}
self.q.push_back(n);
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
self.q.pop_front()
}
}
#[cfg(test)]
mod tests {
use super::LimQ;
#[test]
#[should_panic]
fn zero_len() {
let _q: LimQ<()> = LimQ::new(Some(0));
}
#[test]
fn try_exceed() {
let mut q: LimQ<u32> = LimQ::new(Some(1));
q.try_push(42).unwrap();
assert_eq!(q.len(), 1);
let Err(e) = q.try_push(11) else {
panic!("Unexpectedly not failure");
};
assert_eq!(e, 11);
assert_eq!(q.pop(), Some(42));
assert_eq!(q.len(), 0);
assert_eq!(q.pop(), None);
}
#[test]
fn force_on_full() {
let mut q: LimQ<u32> = LimQ::new(Some(1));
q.force_push(42);
q.force_push(11);
assert_eq!(q.pop(), Some(11));
}
}