use core::iter::FromIterator;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg(feature = "alloc")]
pub struct Queue<A> {
front: Vec<A>,
rear: Vec<A>,
}
#[cfg(feature = "alloc")]
impl<A> Default for Queue<A> {
fn default() -> Self {
Queue::new()
}
}
#[cfg(feature = "alloc")]
impl<A: PartialEq> PartialEq for Queue<A> {
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
return false;
}
let self_iter = self.front.iter().rev().chain(self.rear.iter());
let other_iter = other.front.iter().rev().chain(other.rear.iter());
self_iter.eq(other_iter)
}
}
#[cfg(feature = "alloc")]
impl<A: Eq> Eq for Queue<A> {}
#[cfg(feature = "alloc")]
impl<A> Queue<A> {
#[inline]
pub fn new() -> Self {
Queue {
front: Vec::new(),
rear: Vec::new(),
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.front.is_empty() && self.rear.is_empty()
}
#[inline]
pub fn len(&self) -> usize {
self.front.len() + self.rear.len()
}
#[inline]
pub fn enqueue(mut self, value: A) -> Self {
self.rear.push(value);
Queue {
front: self.front,
rear: self.rear,
}
}
#[inline]
pub fn dequeue(mut self) -> Option<(A, Self)>
where
A: Clone,
{
if self.front.is_empty() {
if self.rear.is_empty() {
return None;
}
core::mem::swap(&mut self.front, &mut self.rear);
self.front.reverse();
}
let value = self.front.pop()?;
Some((
value,
Queue {
front: self.front,
rear: self.rear,
},
))
}
#[inline]
pub fn peek(&self) -> Option<&A> {
if !self.front.is_empty() {
self.front.last()
} else if !self.rear.is_empty() {
self.rear.first()
} else {
None
}
}
#[inline]
pub fn peek_back(&self) -> Option<&A> {
if !self.rear.is_empty() {
self.rear.last()
} else if !self.front.is_empty() {
self.front.first()
} else {
None
}
}
#[inline]
pub fn map<B, F>(&self, f: F) -> Queue<B>
where
A: Clone,
F: Fn(&A) -> B,
{
Queue {
front: self.front.iter().map(&f).collect(),
rear: self.rear.iter().map(&f).collect(),
}
}
#[inline]
pub fn fold<B, F>(&self, init: B, f: F) -> B
where
A: Clone,
F: Fn(B, &A) -> B,
{
let acc = self.front.iter().rfold(init, &f);
self.rear.iter().fold(acc, f)
}
#[inline]
pub fn filter<F>(&self, pred: F) -> Self
where
A: Clone,
F: Fn(&A) -> bool,
{
let front: Vec<A> = self.front.iter().filter(|x| pred(x)).cloned().collect();
let rear: Vec<A> = self.rear.iter().filter(|x| pred(x)).cloned().collect();
Queue { front, rear }
}
#[inline]
pub fn to_vec(&self) -> Vec<A>
where
A: Clone,
{
let mut result: Vec<A> = Vec::with_capacity(self.len());
result.extend(self.front.iter().rev().cloned());
result.extend(self.rear.iter().cloned());
result
}
#[inline]
pub fn concat(&self, other: &Self) -> Self
where
A: Clone,
{
let mut result = self.clone();
for item in other.front.iter().rev() {
result = result.enqueue(item.clone());
}
for item in &other.rear {
result = result.enqueue(item.clone());
}
result
}
}
#[cfg(feature = "alloc")]
impl<A: Clone> From<Vec<A>> for Queue<A> {
fn from(vec: Vec<A>) -> Self {
Queue {
front: Vec::new(),
rear: vec,
}
}
}
#[cfg(feature = "alloc")]
impl<A: Clone> FromIterator<A> for Queue<A> {
fn from_iter<I: IntoIterator<Item = A>>(iter: I) -> Self {
Queue {
front: Vec::new(),
rear: iter.into_iter().collect(),
}
}
}
#[cfg(feature = "alloc")]
pub struct QueueIter<A> {
front: Vec<A>,
rear: Vec<A>,
}
#[cfg(feature = "alloc")]
impl<A> Iterator for QueueIter<A> {
type Item = A;
fn next(&mut self) -> Option<Self::Item> {
if let Some(val) = self.front.pop() {
Some(val)
} else if !self.rear.is_empty() {
core::mem::swap(&mut self.front, &mut self.rear);
self.front.reverse();
self.front.pop()
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.front.len() + self.rear.len();
(len, Some(len))
}
}
#[cfg(feature = "alloc")]
impl<A: Clone> IntoIterator for Queue<A> {
type Item = A;
type IntoIter = QueueIter<A>;
fn into_iter(self) -> Self::IntoIter {
QueueIter {
front: self.front,
rear: self.rear,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::vec;
#[test]
fn test_new_is_empty() {
let q: Queue<i32> = Queue::new();
assert!(q.is_empty());
assert_eq!(q.len(), 0);
}
#[test]
fn test_enqueue_dequeue() {
let q = Queue::new().enqueue(1).enqueue(2).enqueue(3);
assert_eq!(q.len(), 3);
assert_eq!(q.peek(), Some(&1));
let (first, q) = q
.dequeue()
.expect("queue with 3 elements should dequeue first element");
assert_eq!(first, 1);
assert_eq!(q.peek(), Some(&2));
let (second, q) = q
.dequeue()
.expect("queue with 2 elements should dequeue second element");
assert_eq!(second, 2);
assert_eq!(q.peek(), Some(&3));
let (third, q) = q
.dequeue()
.expect("queue with 1 element should dequeue third element");
assert_eq!(third, 3);
assert!(q.is_empty());
}
#[test]
fn test_persistence() {
let q1 = Queue::new().enqueue(1).enqueue(2);
let q2 = q1.clone().enqueue(3);
assert_eq!(q1.len(), 2);
assert_eq!(q1.peek(), Some(&1));
assert_eq!(q2.len(), 3);
}
#[test]
fn test_fifo_order() {
let q = Queue::new().enqueue(1).enqueue(2).enqueue(3);
let items: Vec<_> = q.into_iter().collect();
assert_eq!(items, vec![1, 2, 3]);
}
#[test]
fn test_map() {
let q = Queue::new().enqueue(1).enqueue(2).enqueue(3);
let doubled = q.map(|x| x * 2);
let items: Vec<_> = doubled.into_iter().collect();
assert_eq!(items, vec![2, 4, 6]);
}
#[test]
fn test_fold() {
let q = Queue::new().enqueue(1).enqueue(2).enqueue(3);
let sum = q.fold(0, |acc, x| acc + x);
assert_eq!(sum, 6);
}
#[test]
fn test_filter() {
let q = Queue::new().enqueue(1).enqueue(2).enqueue(3).enqueue(4);
let evens = q.filter(|x| x % 2 == 0);
assert_eq!(evens.len(), 2);
let items: Vec<_> = evens.into_iter().collect();
assert_eq!(items, vec![2, 4]);
}
#[test]
fn test_filter_reject_all_yields_empty_queue() {
let q = Queue::new().enqueue(1).enqueue(2).enqueue(3);
let empty = q.filter(|_| false);
assert!(
empty.is_empty(),
"filter rejecting all elements must be empty"
);
assert_eq!(
empty.len(),
0,
"filter rejecting all elements must have length 0"
);
assert_eq!(
empty.peek(),
None,
"peek on all-rejected filter result must be None"
);
assert!(
empty.dequeue().is_none(),
"dequeue on all-rejected filter result must return None"
);
}
#[test]
fn test_from_vec() {
let v = vec![1, 2, 3];
let q = Queue::from(v);
assert_eq!(q.len(), 3);
assert_eq!(q.peek(), Some(&1));
}
#[test]
fn test_to_vec() {
let q = Queue::new().enqueue(1).enqueue(2).enqueue(3);
assert_eq!(q.to_vec(), vec![1, 2, 3]);
}
#[test]
fn test_concat() {
let q1 = Queue::new().enqueue(1).enqueue(2);
let q2 = Queue::new().enqueue(3).enqueue(4);
let combined = q1.concat(&q2);
assert_eq!(combined.len(), 4);
assert_eq!(combined.to_vec(), vec![1, 2, 3, 4]);
}
#[test]
fn test_concat_with_empty_queue() {
let empty: Queue<i32> = Queue::new();
let non_empty = Queue::new().enqueue(1).enqueue(2).enqueue(3);
let result = empty.concat(&non_empty);
assert_eq!(result.to_vec(), vec![1, 2, 3]);
let result = non_empty.concat(&empty);
assert_eq!(result.to_vec(), vec![1, 2, 3]);
let result = empty.concat(&empty);
assert!(result.is_empty());
}
#[test]
fn test_from_iter() {
let q: Queue<i32> = vec![1, 2, 3].into_iter().collect();
assert_eq!(q.to_vec(), vec![1, 2, 3]);
}
#[test]
fn test_peek_back() {
let q = Queue::new().enqueue(1).enqueue(2).enqueue(3);
assert_eq!(q.peek(), Some(&1));
assert_eq!(q.peek_back(), Some(&3));
}
#[test]
fn test_peek_and_dequeue_on_empty_queue_return_none() {
let q: Queue<i32> = Queue::new();
assert_eq!(q.peek(), None, "peek on empty queue must be None");
assert_eq!(q.peek_back(), None, "peek_back on empty queue must be None");
assert!(
q.dequeue().is_none(),
"dequeue on empty queue must return None"
);
}
}