csq 0.2.1

A Concurrent Set Queue implemented in Safe Rust.
Documentation
use std::{hash::Hash, collections::{VecDeque, HashSet}};

use parking_lot::RwLock;

pub struct RawCSQ<T> {
    queue: VecDeque<T>,
    set: HashSet<T>,
}

impl<T> RawCSQ<T> {
    fn new() -> Self {
        Self {
            queue: VecDeque::new(),
            set: HashSet::new(),
        }
    }
}

pub struct ConcurrentSetQueue<T> {
    inner: RwLock<RawCSQ<T>>
}

impl<T> std::fmt::Debug for ConcurrentSetQueue<T> 
where T: std::fmt::Debug + Eq + Hash {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ConcurrentSetQueue").finish()
    }
}


impl<T> Default for ConcurrentSetQueue<T> 
where T: Eq + Hash {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> ConcurrentSetQueue<T> 
where T: Eq + Hash {
    pub fn new() -> Self {
        Self {
            inner: RwLock::new(RawCSQ::new())
        }
    }

    pub fn pop(&self) -> Option<T> {
        let mut w = self.inner.write();

        if let Some(value) = w.queue.pop_front() {
            w.set.remove(&value);
            return Some(value);
        }

        None
    }

    pub fn drain(&self, amount: usize) -> impl Iterator<Item = T> + '_ {
        (0..amount).map_while(|_| {
            if let Some(value) = self.pop() {
                return Some(value);
            }

            None
        })
    }
}

impl<T> ConcurrentSetQueue<T> 
where T: Eq + Hash + Clone {
    pub fn push(&self, value: T) {
        let mut w = self.inner.write();

        if !w.set.contains(&value) {
            w.set.insert(value.clone());
            w.queue.push_back(value);
        }
    }    
}