use std::sync::Arc;
use std::iter::FromIterator;
use conslist::ConsList;
pub struct Queue<A>(ConsList<A>, ConsList<A>);
impl<A> Queue<A> {
pub fn new() -> Self {
Queue(conslist![], conslist![])
}
pub fn is_empty(&self) -> bool {
self.0.is_empty() && self.1.is_empty()
}
pub fn len(&self) -> usize {
self.0.len() + self.1.len()
}
pub fn push<R>(&self, v: R) -> Self
where
Arc<A>: From<R>,
{
Queue(self.0.clone(), self.1.cons(v))
}
pub fn pop(&self) -> Option<(Arc<A>, Queue<A>)> {
match self {
&Queue(ref l, ref r) if l.is_empty() && r.is_empty() => None,
&Queue(ref l, ref r) => {
match l.uncons() {
None => Queue(r.reverse(), conslist![]).pop(),
Some((a, d)) => Some((a, Queue(d, r.clone()))),
}
}
}
}
pub fn iter(&self) -> Iter<A> {
Iter { current: self.clone() }
}
}
impl<A> Clone for Queue<A> {
fn clone(&self) -> Self {
Queue(self.0.clone(), self.1.clone())
}
}
pub struct Iter<A> {
current: Queue<A>,
}
impl<A> Iterator for Iter<A> {
type Item = Arc<A>;
fn next(&mut self) -> Option<Self::Item> {
match self.current.pop() {
None => None,
Some((a, q)) => {
self.current = q;
Some(a)
}
}
}
}
impl<A> IntoIterator for Queue<A> {
type Item = Arc<A>;
type IntoIter = Iter<A>;
fn into_iter(self) -> Self::IntoIter {
Iter { current: self }
}
}
impl<'a, A> IntoIterator for &'a Queue<A> {
type Item = Arc<A>;
type IntoIter = Iter<A>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<A, T> FromIterator<T> for Queue<A>
where
Arc<A>: From<T>,
{
fn from_iter<I>(source: I) -> Self
where
I: IntoIterator<Item = T>,
{
source.into_iter().fold(Queue::new(), |q, v| q.push(v))
}
}
#[cfg(any(test, feature = "quickcheck"))]
use quickcheck::{Arbitrary, Gen};
#[cfg(any(test, feature = "quickcheck"))]
impl<A: Arbitrary + Sync> Arbitrary for Queue<A> {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
Queue::from_iter(Vec::<A>::arbitrary(g))
}
}
#[cfg(test)]
mod test {
use super::*;
use std::iter::FromIterator;
#[test]
fn general_consistency() {
let q = Queue::new().push(1).push(2).push(3).push(4).push(5).push(6);
assert_eq!(6, q.len());
let vec: Vec<i32> = vec![1, 2, 3, 4, 5, 6];
assert_eq!(vec, Vec::from_iter(q.iter().map(|a| *a)))
}
quickcheck! {
fn length(v: Vec<i32>) -> bool {
let q = Queue::from_iter(v.clone());
v.len() == q.len()
}
fn order(v: Vec<i32>) -> bool {
let q = Queue::from_iter(v.clone());
v == Vec::from_iter(q.iter().map(|a| *a))
}
}
}