use core::hash::Hash;
use crate::RawPhfMap;
#[derive(Debug)]
pub struct PhfSet<K: 'static> {
raw_map: RawPhfMap<K, K>,
}
impl<K> PhfSet<K> {
#[doc(hidden)]
pub const fn new(
seed: u64,
pilots_table: &'static [u16],
elements: &'static [K],
free: &'static [u32],
) -> PhfSet<K> {
PhfSet {
raw_map: RawPhfMap::new(seed, pilots_table, elements, free),
}
}
}
impl<K> PhfSet<K> {
pub const fn len(&self) -> usize {
self.raw_map.len()
}
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn iter(&self) -> Iter<'_, K> {
Iter {
iter: self.raw_map.iter(),
}
}
}
impl<K: Eq + Hash> PhfSet<K> {
pub fn contains(&self, element: &K) -> bool {
self.get(element).is_some()
}
pub fn get(&self, element: &K) -> Option<&K> {
if self.is_empty() {
return None;
}
let result = self.raw_map.get(element);
if result == element {
Some(result)
} else {
None
}
}
pub fn difference<'a>(&'a self, other: &'a PhfSet<K>) -> Difference<'a, K> {
Difference {
iter: self.iter(),
other,
}
}
pub fn intersection<'a>(&'a self, other: &'a PhfSet<K>) -> Intersection<'a, K> {
Intersection {
iter: self.iter(),
other,
}
}
pub fn symmetric_difference<'a>(&'a self, other: &'a PhfSet<K>) -> SymmetricDifference<'a, K> {
SymmetricDifference {
iter: self.difference(other).chain(other.difference(self)),
}
}
pub fn union<'a>(&'a self, other: &'a PhfSet<K>) -> Union<'a, K> {
Union {
iter: self.iter().chain(other.difference(self)),
}
}
pub fn is_disjoint(&self, other: &PhfSet<K>) -> bool {
self.intersection(other).next().is_none()
}
pub fn is_subset(&self, other: &PhfSet<K>) -> bool {
self.difference(other).next().is_none()
}
pub fn is_superset(&self, other: &PhfSet<K>) -> bool {
other.is_subset(self)
}
}
impl<'a, K> IntoIterator for &'a PhfSet<K> {
type Item = &'a K;
type IntoIter = Iter<'a, K>;
fn into_iter(self) -> Iter<'a, K> {
self.iter()
}
}
impl<K: Eq + Hash> PartialEq for PhfSet<K> {
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
return false;
}
self.iter().all(|k| other.contains(k))
}
}
impl<K: Eq + Hash> Eq for PhfSet<K> {}
#[derive(Clone)]
pub struct Iter<'a, K: 'a> {
iter: crate::raw_map::Iter<'a, K>,
}
impl<'a, K> Iterator for Iter<'a, K> {
type Item = &'a K;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, K> ExactSizeIterator for Iter<'a, K> {}
impl<'a, K> core::iter::FusedIterator for Iter<'a, K> {}
#[derive(Clone)]
pub struct Difference<'a, K: 'static> {
iter: Iter<'a, K>,
other: &'a PhfSet<K>,
}
impl<'a, K> Iterator for Difference<'a, K>
where
K: Eq + Hash,
{
type Item = &'a K;
fn next(&mut self) -> Option<Self::Item> {
self.iter.by_ref().find(|&k| !self.other.contains(k))
}
fn size_hint(&self) -> (usize, Option<usize>) {
let self_size = self.iter.size_hint().0;
let other_size = self.other.len();
let min_size = self_size.saturating_sub(other_size);
(min_size, Some(self_size))
}
}
impl<'a, K> core::iter::FusedIterator for Difference<'a, K> where K: Eq + Hash {}
#[derive(Clone)]
pub struct Intersection<'a, K: 'static> {
iter: Iter<'a, K>,
other: &'a PhfSet<K>,
}
impl<'a, K> Iterator for Intersection<'a, K>
where
K: Eq + Hash,
{
type Item = &'a K;
fn next(&mut self) -> Option<Self::Item> {
self.iter.by_ref().find(|&k| self.other.contains(k))
}
fn size_hint(&self) -> (usize, Option<usize>) {
let self_size = self.iter.size_hint().0;
let other_size = self.other.len();
let max_size = usize::min(self_size, other_size);
(0, Some(max_size))
}
}
impl<'a, K> core::iter::FusedIterator for Intersection<'a, K> where K: Eq + Hash {}
#[derive(Clone)]
pub struct SymmetricDifference<'a, K: 'static> {
iter: core::iter::Chain<Difference<'a, K>, Difference<'a, K>>,
}
impl<'a, K> Iterator for SymmetricDifference<'a, K>
where
K: Eq + Hash,
{
type Item = &'a K;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, K> core::iter::FusedIterator for SymmetricDifference<'a, K> where K: Eq + Hash {}
#[derive(Clone)]
pub struct Union<'a, K: 'static> {
iter: core::iter::Chain<Iter<'a, K>, Difference<'a, K>>,
}
impl<'a, K> Iterator for Union<'a, K>
where
K: Eq + Hash,
{
type Item = &'a K;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, K> core::iter::FusedIterator for Union<'a, K> where K: Eq + Hash {}
#[cfg(test)]
mod tests {
use crate::examples::EMPTY_SET;
use super::*;
#[test]
fn test_empty() {
assert_eq!(EMPTY_SET.get(&17), None);
assert!(!EMPTY_SET.contains(&620));
assert!(EMPTY_SET.iter().next().is_none())
}
#[test]
fn test_sync() {
fn assert_sync<T: Sync>() {}
assert_sync::<PhfSet<u64>>();
}
}