#![allow(dead_code)]
use std::borrow::Borrow;
use std::fmt;
use std::hash::Hash;
use chashmap::CHashMap;
#[derive(Clone)]
pub struct CHashSet<K> {
map: CHashMap<K, ()>,
}
pub type ReadGuard<'a, K> = chashmap::ReadGuard<'a, K, ()>;
pub type WriteGuard<'a, K> = chashmap::WriteGuard<'a, K, ()>;
impl<T> CHashSet<T> {
#[inline]
pub fn new() -> CHashSet<T> {
CHashSet {
map: CHashMap::new(),
}
}
#[inline]
pub fn with_capacity(capacity: usize) -> CHashSet<T> {
CHashSet {
map: CHashMap::with_capacity(capacity),
}
}
#[inline]
pub fn capacity(&self) -> usize {
self.map.capacity()
}
#[inline]
pub fn len(&self) -> usize {
self.map.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
#[inline]
pub fn clear(&self) {
self.map.clear();
}
pub fn retain<F>(&self, f: F)
where
F: Fn(&T) -> bool,
{
self.map.retain(|k, _| f(k));
}
}
impl<T> CHashSet<T>
where
T: PartialEq + Hash,
{
#[inline]
pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<ReadGuard<T>>
where
T: Borrow<Q>,
Q: Hash + PartialEq,
{
self.map.get(value)
}
#[inline]
pub fn reserve(&self, additional: usize) {
self.map.reserve(additional)
}
#[inline]
pub fn shrink_to_fit(&self) {
self.map.shrink_to_fit()
}
#[inline]
pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
where
T: Borrow<Q>,
Q: Hash + PartialEq,
{
self.map.contains_key(value)
}
#[inline]
pub fn insert_new(&self, value: T) {
self.map.insert_new(value, ())
}
#[inline]
pub fn insert(&self, value: T) -> bool {
self.map.insert(value, ()).is_none()
}
#[inline]
pub fn remove<Q: ?Sized>(&self, value: &Q) -> bool
where
T: Borrow<Q>,
Q: Hash + PartialEq,
{
self.map.remove(value).is_some()
}
}
impl<T> fmt::Debug for CHashSet<T>
where
T: PartialEq + Hash + fmt::Debug + Clone,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_set().entries(self.clone().into_iter()).finish()
}
}
impl<T> std::iter::FromIterator<T> for CHashSet<T>
where
T: PartialEq + Hash,
{
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> CHashSet<T> {
CHashSet {
map: CHashMap::from_iter(iter.into_iter().map(|k| (k, ()))),
}
}
}
impl<T> Default for CHashSet<T>
where
T: PartialEq + Hash,
{
#[inline]
fn default() -> CHashSet<T> {
CHashSet {
map: CHashMap::default(),
}
}
}
pub struct IntoIter<K> {
iter: chashmap::IntoIter<K, ()>,
}
impl<T> IntoIterator for CHashSet<T> {
type Item = T;
type IntoIter = IntoIter<T>;
#[inline]
fn into_iter(self) -> IntoIter<T> {
IntoIter {
iter: self.map.into_iter(),
}
}
}
impl<K> Iterator for IntoIter<K> {
type Item = K;
#[inline]
fn next(&mut self) -> Option<K> {
self.iter.next().map(|(k, _)| k)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<K> std::iter::FusedIterator for IntoIter<K> {}
#[cfg(test)]
mod test_set {
use super::CHashSet;
#[test]
fn test_from_iter() {
let xs = [1, 2, 2, 3, 4, 5, 6, 7, 8, 9];
let set: CHashSet<_> = xs.iter().cloned().collect();
for x in &xs {
assert!(set.contains(x));
}
}
#[test]
fn test_move_iter() {
let hs = {
let hs = CHashSet::new();
hs.insert('a');
hs.insert('b');
hs
};
let v = hs.into_iter().collect::<Vec<char>>();
assert!(v == ['a', 'b'] || v == ['b', 'a']);
}
#[test]
fn test_show() {
let set = CHashSet::new();
let empty = CHashSet::<i32>::new();
set.insert(1);
set.insert(2);
let set_str = format!("{:?}", set);
assert!(set_str == "{1, 2}" || set_str == "{2, 1}");
assert_eq!(format!("{:?}", empty), "{}");
}
#[test]
fn test_retain() {
let xs = [1, 2, 3, 4, 5, 6];
let set: CHashSet<i32> = xs.iter().cloned().collect();
set.retain(|&k| k % 2 == 0);
assert_eq!(set.len(), 3);
assert!(set.contains(&2));
assert!(set.contains(&4));
assert!(set.contains(&6));
}
}