use std::collections::{HashSet, VecDeque};
pub(crate) struct UniDeque<T> {
queue: VecDeque<T>,
set: HashSet<T>,
}
impl<T: Eq + std::hash::Hash + Clone> UniDeque<T> {
pub(crate) fn new() -> Self {
UniDeque {
queue: VecDeque::new(),
set: HashSet::new(),
}
}
pub(crate) fn push_unique(&mut self, value: T) -> bool {
let new = self.set.insert(value.clone());
if new {
self.queue.push_back(value)
}
new
}
pub(crate) fn drain_first_n(&mut self, n: usize) -> Vec<T> {
let n = n.min(self.len());
let drained = self.queue.drain(..n).inspect(|item| {
self.set.remove(item);
});
drained.collect()
}
#[allow(dead_code)]
pub(crate) fn contains(&self, value: &T) -> bool {
self.set.contains(value)
}
pub(crate) fn len(&self) -> usize {
self.queue.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_creates_empty() {
let d: UniDeque<i32> = UniDeque::new();
assert_eq!(d.len(), 0);
assert!(!d.contains(&1));
}
#[test]
fn push_unique_and_contains() {
let mut d = UniDeque::new();
d.push_unique(1);
d.push_unique(2);
d.push_unique(3);
assert_eq!(d.len(), 3);
assert!(d.contains(&1));
assert!(d.contains(&2));
assert!(d.contains(&3));
assert!(!d.contains(&0));
assert!(!d.contains(&4));
}
#[test]
fn push_unique_duplicate() {
let mut d = UniDeque::new();
assert_eq!(d.push_unique(42), true);
assert_eq!(d.push_unique(42), false);
assert_eq!(d.push_unique(42), false);
assert!(d.contains(&42));
assert_eq!(d.len(), 1);
}
#[test]
fn drain_removes_all_items() {
let mut d = UniDeque::new();
d.push_unique(10);
d.push_unique(20);
d.push_unique(30);
let drained = d.drain_first_n(3);
assert_eq!(drained, vec![10, 20, 30]);
assert_eq!(d.len(), 0);
assert!(!d.contains(&10));
assert!(!d.contains(&20));
assert!(!d.contains(&30));
}
#[test]
fn drain_partial_consumption() {
let mut d = UniDeque::new();
d.push_unique(1);
d.push_unique(2);
d.push_unique(3);
let drained = d.drain_first_n(3);
assert_eq!(drained, vec![1, 2, 3]);
assert_eq!(d.len(), 0);
assert!(!d.contains(&1));
assert!(!d.contains(&2));
assert!(!d.contains(&3));
}
#[test]
fn drain_more_than_available() {
let mut d = UniDeque::new();
d.push_unique(7);
let drained = d.drain_first_n(100);
assert_eq!(drained, vec![7]);
assert_eq!(d.len(), 0);
}
#[test]
fn drain_re_enqueue() {
let mut d = UniDeque::new();
d.push_unique(1);
d.push_unique(2);
d.push_unique(3);
let drained = d.drain_first_n(3);
assert_eq!(drained, vec![1, 2, 3]);
d.push_unique(1);
assert_eq!(d.len(), 1);
assert!(d.contains(&1));
}
#[test]
fn len_after_mutations() {
let mut d = UniDeque::new();
assert_eq!(d.len(), 0);
d.push_unique(10);
assert_eq!(d.len(), 1);
d.push_unique(20);
assert_eq!(d.len(), 2);
d.drain_first_n(1);
assert_eq!(d.len(), 1);
}
}