use std::{
borrow::Borrow,
default::Default,
fmt,
hash::{BuildHasher, Hash},
iter::FusedIterator,
marker::PhantomData,
ops::AddAssign,
};
use hashbrown::{
hash_map::DefaultHashBuilder,
hash_set,
raw::{RawIter, RawTable},
HashSet,
};
use crate::utils::*;
#[cfg(doc)]
use hashbrown::HashMap;
pub(crate) fn equivalent_key_left<T: Borrow<Q>, Q: PartialEq + ?Sized>(
k: &Q,
) -> impl Fn(&LeftItem<T>) -> bool + '_ {
move |x| x.value.borrow().eq(k)
}
pub(crate) fn equivalent_key_right<T: Borrow<Q>, Q: PartialEq + ?Sized>(
k: &Q,
) -> impl Fn(&RightItem<T>) -> bool + '_ {
move |x| x.value.borrow().eq(k)
}
pub(crate) fn left_with_left_id<T: PartialEq + ?Sized>(id: ID) -> impl Fn(&LeftItem<T>) -> bool {
move |x| x.id == id
}
pub(crate) fn right_with_left_pair<T: PartialEq + ?Sized>(
pair: &(u64, ID),
) -> impl Fn(&RightItem<T>) -> bool + '_ {
move |x| x.pairs.contains(pair)
}
pub(crate) fn right_with_right_id<T: PartialEq + ?Sized>(id: ID) -> impl Fn(&RightItem<T>) -> bool {
move |x| x.id == id
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub(crate) struct ID(u64);
pub(crate) struct LeftItem<T> {
pub(crate) value: T,
pub(crate) hash: u64,
pub(crate) r_id: ID,
pub(crate) id: ID,
}
pub(crate) struct RightItem<T> {
pub(crate) value: T,
pub(crate) pairs: HashSet<(u64, ID)>, pub(crate) id: ID, }
pub struct GroupMap<L, R, St = DefaultHashBuilder> {
pub(crate) hash_builder: St,
pub(crate) left_counter: ID,
pub(crate) right_counter: ID,
left_set: RawTable<LeftItem<L>>,
right_set: RawTable<RightItem<R>>,
}
impl<L, R> GroupMap<L, R, DefaultHashBuilder> {
#[inline]
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self::with_capacity_and_hasher(capacity, DefaultHashBuilder::default())
}
}
impl<L, R, S> GroupMap<L, R, S>
where
L: Eq + Hash,
R: Eq + Hash,
S: BuildHasher,
{
pub fn insert(&mut self, left: L, right: R) {
let l_hash = make_hash::<L, S>(&self.hash_builder, &left);
let r_hash = make_hash::<R, S>(&self.hash_builder, &right);
let opt_left = self.left_set.get_mut(l_hash, equivalent_key_left(&left));
let opt_right = self.right_set.get_mut(r_hash, equivalent_key_right(&right));
match (opt_left, opt_right) {
(None, None) => {
let left_item = LeftItem {
value: left,
hash: r_hash,
r_id: self.right_counter,
id: self.left_counter,
};
self.left_set
.insert(l_hash, left_item, make_hasher(&self.hash_builder));
let mut set = HashSet::with_capacity(1);
set.insert((l_hash, self.left_counter));
let right_item = RightItem {
value: right,
pairs: set,
id: self.right_counter,
};
self.right_set
.insert(r_hash, right_item, make_hasher(&self.hash_builder));
self.left_counter.0 += 1;
self.right_counter.0 += 1;
}
(Some(l), None) => {
let pair = (l_hash, l.id);
let r = self
.right_set
.get_mut(l.hash, right_with_left_pair(&pair))
.unwrap();
l.hash = r_hash;
l.r_id = self.right_counter;
r.pairs.remove(&pair);
let mut set = HashSet::with_capacity(1);
set.insert(pair);
let right_item = RightItem {
value: right,
pairs: set,
id: self.right_counter,
};
self.right_set
.insert(r_hash, right_item, make_hasher(&self.hash_builder));
self.right_counter.0 += 1;
}
(None, Some(r)) => {
r.pairs.insert((l_hash, self.left_counter));
let left_item = LeftItem {
value: left,
hash: r_hash,
id: self.left_counter,
r_id: r.id,
};
self.left_set
.insert(l_hash, left_item, make_hasher(&self.hash_builder));
self.left_counter.0 += 1;
}
(Some(l), Some(r)) => {
let pair = (l_hash, l.id);
r.pairs.insert(pair);
let new_r_id = r.id;
self.right_set
.get_mut(l.hash, right_with_right_id(l.r_id))
.unwrap()
.pairs
.remove(&pair);
l.hash = r_hash;
l.r_id = new_r_id;
}
}
}
pub fn insert_remove(&mut self, left: L, right: R) -> (Option<L>, Option<(HashSet<L>, R)>) {
let opt_from_left = self.remove_left(&left);
let opt_from_right = self.remove_right(&right);
let digest = (opt_from_left, opt_from_right);
let l_hash = make_hash::<L, S>(&self.hash_builder, &left);
let r_hash = make_hash::<R, S>(&self.hash_builder, &right);
let left_item = LeftItem {
value: left,
hash: r_hash,
id: self.left_counter,
r_id: self.right_counter,
};
let mut set = HashSet::with_capacity(1);
set.insert((l_hash, self.left_counter));
let right_item = RightItem {
value: right,
pairs: set,
id: self.right_counter,
};
self.left_counter.0 += 1;
self.right_counter.0 += 1;
self.left_set
.insert(l_hash, left_item, make_hasher(&self.hash_builder));
self.right_set
.insert(r_hash, right_item, make_hasher(&self.hash_builder));
digest
}
pub fn insert_left(&mut self, left: L, right: &R) -> Option<L> {
let r_hash = make_hash::<R, S>(&self.hash_builder, right);
let right_item = self
.right_set
.get_mut(r_hash, equivalent_key_right(right))?;
let right_id = right_item.id;
let l_hash = make_hash::<L, S>(&self.hash_builder, &left);
right_item.pairs.insert((l_hash, self.left_counter));
let digest = self.remove_left(&left);
let left_item = LeftItem {
value: left,
hash: r_hash,
id: self.left_counter,
r_id: right_id,
};
self.left_counter += 1;
self.left_set.insert(
l_hash,
left_item,
make_hasher::<LeftItem<L>, S>(&self.hash_builder),
);
digest
}
pub fn insert_right(&mut self, right: R) -> Option<(HashSet<L>, R)> {
let digest = self.remove_right(&right);
let r_hash = make_hash::<R, S>(&self.hash_builder, &right);
let right_item = RightItem {
value: right,
pairs: HashSet::new(),
id: self.right_counter,
};
self.right_counter += 1;
self.right_set.insert(
r_hash,
right_item,
make_hasher::<RightItem<R>, S>(&self.hash_builder),
);
digest
}
pub fn swap_right(&mut self, old: &R, new: R) {
let old_hash = make_hash::<R, S>(&self.hash_builder, old);
match self.right_set.get_mut(old_hash, equivalent_key_right(old)) {
None => {
self.insert_right(new);
}
Some(r) => {
let set: HashSet<(u64, ID)> = r.pairs.drain().collect();
let new_hash = make_hash::<R, S>(&self.hash_builder, &new);
let item = RightItem {
value: new,
pairs: set.clone(),
id: self.right_counter,
};
self.right_set
.insert(new_hash, item, make_hasher(&self.hash_builder));
self.right_counter += 1;
for (hash, id) in set {
self.left_set
.get_mut(hash, left_with_left_id(id))
.unwrap()
.hash = new_hash;
}
}
}
}
pub fn swap_right_remove(&mut self, old: &R, new: R) -> Option<R> {
let old_hash = make_hash::<R, S>(&self.hash_builder, old);
match self
.right_set
.remove_entry(old_hash, equivalent_key_right(old))
{
None => {
self.insert_right(new);
None
}
Some(mut r) => {
let set: HashSet<(u64, ID)> = r.pairs.drain().collect();
let new_hash = make_hash::<R, S>(&self.hash_builder, &new);
let item = RightItem {
value: new,
pairs: set.clone(),
id: self.right_counter,
};
self.right_set
.insert(new_hash, item, make_hasher(&self.hash_builder));
self.right_counter += 1;
for (hash, id) in set {
self.left_set
.get_mut(hash, left_with_left_id(id))
.unwrap()
.hash = new_hash;
}
Some(r.value)
}
}
}
pub fn pair(&mut self, left: &L, right: &R) -> bool {
let l_hash = make_hash::<L, S>(&self.hash_builder, left);
let r_hash = make_hash::<R, S>(&self.hash_builder, right);
let opt_left = self.left_set.get_mut(l_hash, equivalent_key_left(left));
let opt_right = self.right_set.get(r_hash, equivalent_key_right(right));
let (digest, to_remove) = match (opt_left, opt_right) {
(Some(left), Some(r)) => {
let to_remove = Some((left.hash, left.r_id, left.id));
left.hash = r_hash;
left.r_id = r.id;
(true, to_remove)
}
_ => (false, None),
};
if let Some(triple) = to_remove {
let old_right = self
.right_set
.get_mut(triple.0, right_with_right_id(triple.1))
.unwrap();
old_right.pairs.remove(&(l_hash, triple.2));
let new_right = self
.right_set
.get_mut(r_hash, equivalent_key_right(right))
.unwrap();
new_right.pairs.insert((l_hash, triple.2));
}
digest
}
pub fn is_right_paired(&self, right: &R) -> bool {
let r_hash = make_hash::<R, S>(&self.hash_builder, right);
let opt_right = self.right_set.get(r_hash, equivalent_key_right(right));
match opt_right {
Some(r) => !r.pairs.is_empty(),
None => false,
}
}
pub fn are_paired(&self, left: &L, right: &R) -> bool {
let l_hash = make_hash::<L, S>(&self.hash_builder, left);
let r_hash = make_hash::<R, S>(&self.hash_builder, right);
let opt_left = self.left_set.get(l_hash, equivalent_key_left(left));
let opt_right = self.right_set.get(r_hash, equivalent_key_right(right));
match (opt_left, opt_right) {
(Some(left), Some(right)) => {
left.hash == r_hash && right.pairs.contains(&(l_hash, left.id))
}
_ => false,
}
}
pub fn contains_left(&self, left: &L) -> bool {
let hash = make_hash::<L, S>(&self.hash_builder, left);
self.left_set.get(hash, equivalent_key_left(left)).is_some()
}
pub fn contains_right(&self, right: &R) -> bool {
let hash = make_hash::<R, S>(&self.hash_builder, right);
self.right_set
.get(hash, equivalent_key_right(right))
.is_some()
}
pub fn remove(&mut self, left: &L, right: &R) -> Option<(HashSet<L>, R)> {
if self.are_paired(left, right) {
self.remove_right(right)
} else {
None
}
}
pub fn remove_left(&mut self, item: &L) -> Option<L> {
let l_hash = make_hash::<L, S>(&self.hash_builder, item);
let left_item = self
.left_set
.remove_entry(l_hash, equivalent_key_left(item))?;
let pair = (l_hash, left_item.id);
self.right_set
.get_mut(left_item.hash, right_with_left_pair(&pair))
.unwrap()
.pairs
.remove(&pair);
Some(left_item.extract())
}
pub fn remove_right(&mut self, item: &R) -> Option<(HashSet<L>, R)> {
let r_hash = make_hash::<R, S>(&self.hash_builder, item);
let right_item = self
.right_set
.remove_entry(r_hash, equivalent_key_right(item))?;
let left_vec: HashSet<L> = right_item
.pairs
.iter()
.map(|(h, i)| {
self.left_set
.remove_entry(*h, left_with_left_id(*i))
.unwrap()
.extract()
})
.collect();
Some((left_vec, right_item.extract()))
}
fn remove_via_hash_and_id(&mut self, r_hash: u64, id: ID) -> Option<(Vec<L>, R)> {
let right = self
.right_set
.remove_entry(r_hash, right_with_right_id(id))?;
let left_vec = right
.pairs
.iter()
.map(|(h, i)| {
self.left_set
.remove_entry(*h, left_with_left_id(*i))
.unwrap()
.extract()
})
.collect();
Some((left_vec, right.extract()))
}
pub fn get_left_iter<Q>(&self, item: &Q) -> Option<PairIter<'_, L, R, S>>
where
R: Borrow<Q>,
Q: Hash + Eq,
{
let r_hash = make_hash::<_, S>(&self.hash_builder, item);
let right_item: &RightItem<R> = self.right_set.get(r_hash, equivalent_key_right(item))?;
Some(PairIter {
iter: right_item.pairs.iter(),
map_ref: self,
marker: PhantomData,
})
}
pub fn get_right<Q>(&self, item: &Q) -> Option<&R>
where
L: Borrow<Q>,
Q: Hash + Eq,
{
let l_hash = make_hash::<_, S>(&self.hash_builder, item);
let left_item = self.get_left_inner_with_hash(item, l_hash)?;
match self
.right_set
.get(left_item.hash, right_with_right_id(left_item.r_id))
{
None => None,
Some(pairing) => Some(&pairing.value),
}
}
#[inline]
fn get_left_inner_with_hash<Q>(&self, item: &Q, hash: u64) -> Option<&LeftItem<L>>
where
L: Borrow<Q>,
Q: Hash + Eq,
{
self.left_set.get(hash, equivalent_key_left(item))
}
#[inline]
fn get_right_inner_with_hash<Q>(&self, item: &Q, hash: u64) -> Option<&RightItem<R>>
where
R: Borrow<Q>,
Q: Hash + Eq,
{
self.right_set.get(hash, equivalent_key_right(item))
}
pub fn iter(&self) -> Iter<'_, L, R, S> {
Iter {
right_iter: unsafe { self.right_set.iter() },
left_iter: None,
map_ref: self,
}
}
pub fn iter_paired(&self) -> PairedIter<'_, L, R, S> {
PairedIter {
left_iter: unsafe { self.left_set.iter() },
map_ref: self,
}
}
pub fn iter_unpaired(&self) -> UnpairedIter<'_, L, R, S> {
UnpairedIter {
right_iter: unsafe { self.right_set.iter() },
map_ref: self,
}
}
pub fn iter_left(&self) -> LeftIter<'_, L> {
LeftIter {
left_iter: unsafe { self.left_set.iter() },
marker: PhantomData,
}
}
pub fn iter_right(&self) -> RightIter<'_, R> {
RightIter {
right_iter: unsafe { self.right_set.iter() },
marker: PhantomData,
}
}
pub fn retain_paired<F>(&mut self, mut f: F)
where
F: FnMut(&L, &R) -> bool,
{
let mut to_drop: Vec<(u64, ID)> = Vec::with_capacity(self.left_set.len());
for (l, r) in self.iter_paired() {
if f(l, r) {
let l_hash = make_hash(&self.hash_builder, l);
let l_item = self.get_left_inner_with_hash(l, l_hash).unwrap();
to_drop.push((l_hash, l_item.id));
}
}
for (l_hash, id) in to_drop {
self.left_set.remove_entry(l_hash, left_with_left_id(id));
}
}
pub fn retain_unpaired<F>(&mut self, mut f: F)
where
F: FnMut(&R) -> bool,
{
let mut to_drop: Vec<(u64, ID)> = Vec::with_capacity(self.left_set.len());
for r in self.iter_unpaired() {
if f(r) {
let r_hash = make_hash::<R, S>(&self.hash_builder, r);
let r_item = self.get_right_inner_with_hash(r, r_hash).unwrap();
to_drop.push((r_hash, r_item.id));
}
}
for (r_hash, id) in to_drop {
self.remove_via_hash_and_id(r_hash, id);
}
}
}
impl<L, R, S> Clone for GroupMap<L, R, S>
where
L: Eq + Hash + Clone,
R: Eq + Hash + Clone,
S: BuildHasher + Clone,
{
fn clone(&self) -> Self {
Self {
left_set: self.left_set.clone(),
right_set: self.right_set.clone(),
left_counter: self.left_counter,
right_counter: self.right_counter,
hash_builder: self.hash_builder.clone(),
}
}
}
impl<L, R, S> Default for GroupMap<L, R, S>
where
S: Default,
{
fn default() -> Self {
Self::with_hasher(Default::default())
}
}
impl<L, R, S> fmt::Debug for GroupMap<L, R, S>
where
L: Hash + Eq + fmt::Debug,
R: Hash + Eq + fmt::Debug,
S: BuildHasher,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_set().entries(self.iter()).finish()
}
}
impl<L, R, S> PartialEq<GroupMap<L, R, S>> for GroupMap<L, R, S>
where
L: Hash + Eq,
R: Hash + Eq,
S: BuildHasher,
{
fn eq(&self, other: &Self) -> bool {
if self.len_left() != other.len_left() && self.len_right() != other.len_right() {
return false;
}
self.iter().all(|(l_opt, r)| match l_opt {
Some(l) => other.are_paired(l, r),
None => !other.is_right_paired(r),
})
}
}
impl<L, R, S> Eq for GroupMap<L, R, S>
where
L: Hash + Eq,
R: Hash + Eq,
S: BuildHasher,
{
}
impl<L, R, S> GroupMap<L, R, S> {
pub const fn with_hasher(hash_builder: S) -> Self {
Self {
hash_builder,
left_counter: ID(0),
right_counter: ID(0),
left_set: RawTable::new(),
right_set: RawTable::new(),
}
}
pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self {
Self {
hash_builder,
left_counter: ID(0),
right_counter: ID(0),
left_set: RawTable::with_capacity(capacity),
right_set: RawTable::with_capacity(capacity),
}
}
pub fn hasher(&self) -> &S {
&self.hash_builder
}
pub fn capacity_left(&self) -> usize {
self.left_set.capacity()
}
pub fn capacity_right(&self) -> usize {
self.right_set.capacity()
}
pub fn len_left(&self) -> usize {
self.left_set.len()
}
pub fn len_right(&self) -> usize {
self.right_set.len()
}
pub fn is_empty(&self) -> bool {
self.len_left() + self.len_right() == 0
}
pub fn clear(&mut self) {
self.left_set.clear();
self.right_set.clear();
}
}
impl<L, R, S> Extend<(Option<L>, R)> for GroupMap<L, R, S>
where
L: Hash + Eq,
R: Hash + Eq,
S: BuildHasher,
{
#[inline]
fn extend<T: IntoIterator<Item = (Option<L>, R)>>(&mut self, iter: T) {
for (left, right) in iter {
if let Some(l) = left {
self.insert(l, right);
} else {
self.insert_right(right);
}
}
}
}
impl<L, R, S> Extend<(L, R)> for GroupMap<L, R, S>
where
L: Hash + Eq,
R: Hash + Eq,
S: BuildHasher,
{
#[inline]
fn extend<T: IntoIterator<Item = (L, R)>>(&mut self, iter: T) {
for (left, right) in iter {
self.insert(left, right);
}
}
}
impl<L, R> FromIterator<(Option<L>, R)> for GroupMap<L, R>
where
L: Hash + Eq,
R: Hash + Eq,
{
fn from_iter<T: IntoIterator<Item = (Option<L>, R)>>(iter: T) -> Self {
let mut digest = GroupMap::default();
digest.extend(iter);
digest
}
}
impl<L, R> FromIterator<(L, R)> for GroupMap<L, R>
where
L: Hash + Eq,
R: Hash + Eq,
{
fn from_iter<T: IntoIterator<Item = (L, R)>>(iter: T) -> Self {
let mut digest = GroupMap::default();
digest.extend(iter);
digest
}
}
pub struct Iter<'a, L, R, S> {
right_iter: RawIter<RightItem<R>>,
left_iter: Option<hash_set::Iter<'a, (u64, ID)>>,
map_ref: &'a GroupMap<L, R, S>,
}
impl<L, R, S> Clone for Iter<'_, L, R, S> {
fn clone(&self) -> Self {
Self {
right_iter: self.right_iter.clone(),
left_iter: None,
map_ref: self.map_ref,
}
}
}
impl<L, R, S> fmt::Debug for Iter<'_, L, R, S>
where
L: Hash + Eq + fmt::Debug,
R: Hash + Eq + fmt::Debug,
S: BuildHasher,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}
impl<'a, L, R, S> Iterator for Iter<'a, L, R, S>
where
L: Hash + Eq,
R: Hash + Eq,
S: BuildHasher,
{
type Item = (Option<&'a L>, &'a R);
fn next(&mut self) -> Option<Self::Item> {
if let Some(iter) = self.left_iter.as_mut() {
if let Some(pair) = iter.next() {
let left = self
.map_ref
.left_set
.get(pair.0, left_with_left_id(pair.1))
.unwrap();
let right = self
.map_ref
.right_set
.get(left.hash, right_with_right_id(left.r_id))
.unwrap();
return Some((Some(&left.value), &right.value));
}
}
match self.right_iter.next() {
Some(r) => {
let r_ref = unsafe { &r.as_ref() };
if r_ref.pairs.is_empty() {
Some((None, &r_ref.value))
} else {
let mut iter = r_ref.pairs.iter();
let pair = iter.next().unwrap();
self.left_iter = Some(iter);
let left = self
.map_ref
.left_set
.get(pair.0, left_with_left_id(pair.1))
.map(|o| &o.value);
Some((left, &r_ref.value))
}
}
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.right_iter.size_hint()
}
}
impl<'a, L, R, S> ExactSizeIterator for Iter<'a, L, R, S>
where
L: Hash + Eq,
R: Hash + Eq,
S: BuildHasher,
{
fn len(&self) -> usize {
self.clone().count()
}
}
impl<L, R, S> FusedIterator for Iter<'_, L, R, S>
where
L: Hash + Eq,
R: Hash + Eq,
S: BuildHasher,
{
}
pub struct PairedIter<'a, L, R, S> {
left_iter: RawIter<LeftItem<L>>,
map_ref: &'a GroupMap<L, R, S>,
}
impl<L, R, S> Clone for PairedIter<'_, L, R, S> {
fn clone(&self) -> Self {
Self {
left_iter: self.left_iter.clone(),
map_ref: self.map_ref,
}
}
}
impl<L, R, S> fmt::Debug for PairedIter<'_, L, R, S>
where
L: Hash + Eq + fmt::Debug,
R: Hash + Eq + fmt::Debug,
S: BuildHasher,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}
impl<'a, L, R, S> Iterator for PairedIter<'a, L, R, S>
where
L: Hash + Eq,
R: Hash + Eq,
S: BuildHasher,
{
type Item = (&'a L, &'a R);
fn next(&mut self) -> Option<Self::Item> {
match self.left_iter.next() {
Some(l_bucket) => {
let l_item = unsafe { l_bucket.as_ref() };
let r_item = self
.map_ref
.right_set
.get(l_item.hash, right_with_right_id(l_item.r_id))
.unwrap();
Some((&l_item.value, &r_item.value))
}
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.left_iter.size_hint()
}
}
impl<'a, L, R, S> ExactSizeIterator for PairedIter<'a, L, R, S>
where
L: Hash + Eq,
R: Hash + Eq,
S: BuildHasher,
{
fn len(&self) -> usize {
self.clone().count()
}
}
impl<L, R, S> FusedIterator for PairedIter<'_, L, R, S>
where
L: Hash + Eq,
R: Hash + Eq,
S: BuildHasher,
{
}
pub struct UnpairedIter<'a, L, R, S> {
right_iter: RawIter<RightItem<R>>,
map_ref: &'a GroupMap<L, R, S>,
}
impl<L, R, S> Clone for UnpairedIter<'_, L, R, S> {
fn clone(&self) -> Self {
Self {
right_iter: self.right_iter.clone(),
map_ref: self.map_ref,
}
}
}
impl<L, R, S> fmt::Debug for UnpairedIter<'_, L, R, S>
where
L: Hash + Eq + fmt::Debug,
R: Hash + Eq + fmt::Debug,
S: BuildHasher,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}
impl<'a, L, R, S> Iterator for UnpairedIter<'a, L, R, S>
where
L: Hash + Eq,
R: Hash + Eq,
S: BuildHasher,
{
type Item = &'a R;
fn next(&mut self) -> Option<Self::Item> {
while let Some(item) = self.right_iter.next().map(|r| unsafe { r.as_ref() }) {
if item.pairs.is_empty() {
return Some(&item.value);
}
}
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.right_iter.size_hint()
}
}
impl<'a, L, R, S> ExactSizeIterator for UnpairedIter<'a, L, R, S>
where
L: Hash + Eq,
R: Hash + Eq,
S: BuildHasher,
{
fn len(&self) -> usize {
self.clone().count()
}
}
impl<L, R, S> FusedIterator for UnpairedIter<'_, L, R, S>
where
L: Hash + Eq,
R: Hash + Eq,
S: BuildHasher,
{
}
pub struct LeftIter<'a, L> {
left_iter: RawIter<LeftItem<L>>,
marker: PhantomData<&'a L>,
}
impl<L> Clone for LeftIter<'_, L> {
fn clone(&self) -> Self {
Self {
left_iter: self.left_iter.clone(),
marker: PhantomData,
}
}
}
impl<L> fmt::Debug for LeftIter<'_, L>
where
L: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}
impl<'a, L> Iterator for LeftIter<'a, L> {
type Item = &'a L;
fn next(&mut self) -> Option<Self::Item> {
self.left_iter.next().map(|b| unsafe { &b.as_ref().value })
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.left_iter.size_hint()
}
}
impl<L> ExactSizeIterator for LeftIter<'_, L> {
fn len(&self) -> usize {
self.left_iter.len()
}
}
impl<L> FusedIterator for LeftIter<'_, L> {}
pub struct RightIter<'a, R> {
right_iter: RawIter<RightItem<R>>,
marker: PhantomData<&'a R>,
}
impl<R> Clone for RightIter<'_, R> {
fn clone(&self) -> Self {
Self {
right_iter: self.right_iter.clone(),
marker: PhantomData,
}
}
}
impl<R> fmt::Debug for RightIter<'_, R>
where
R: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}
impl<'a, R> Iterator for RightIter<'a, R> {
type Item = &'a R;
fn next(&mut self) -> Option<Self::Item> {
self.right_iter.next().map(|b| unsafe { &b.as_ref().value })
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.right_iter.size_hint()
}
}
impl<R> ExactSizeIterator for RightIter<'_, R> {
fn len(&self) -> usize {
self.right_iter.len()
}
}
impl<R> FusedIterator for RightIter<'_, R> {}
pub struct PairIter<'a, L, R, S> {
iter: hash_set::Iter<'a, (u64, ID)>,
map_ref: &'a GroupMap<L, R, S>,
marker: PhantomData<&'a L>,
}
impl<L, R, S> Clone for PairIter<'_, L, R, S> {
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
map_ref: self.map_ref,
marker: PhantomData,
}
}
}
impl<L, R, S> fmt::Debug for PairIter<'_, L, R, S>
where
L: Eq + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}
impl<'a, L, R, S> Iterator for PairIter<'a, L, R, S>
where
L: Eq,
{
type Item = &'a L;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(hash, id)| {
&self
.map_ref
.left_set
.get(*hash, left_with_left_id(*id))
.unwrap()
.value
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<L, R, S> ExactSizeIterator for PairIter<'_, L, R, S>
where
L: Eq,
{
fn len(&self) -> usize {
self.iter.len()
}
}
impl<L: Eq, R, S> FusedIterator for PairIter<'_, L, R, S> {}
impl<T> LeftItem<T> {
pub(crate) fn extract(self) -> T {
self.value
}
}
impl<T: Hash> Hash for LeftItem<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.value.hash(state)
}
}
impl<T: PartialEq> PartialEq for LeftItem<T> {
fn eq(&self, other: &Self) -> bool {
self.id.eq(&other.id) && self.value.eq(&other.value)
}
}
impl<T> Eq for LeftItem<T> where T: Hash + Eq {}
impl<T: Clone> Clone for LeftItem<T> {
fn clone(&self) -> Self {
Self {
value: self.value.clone(),
hash: self.hash,
r_id: self.r_id,
id: self.id,
}
}
}
impl<T: fmt::Debug> fmt::Debug for LeftItem<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"LeftItem {{ value: {:?}, hash: {}, id: {} }}",
self.value, self.hash, self.id.0
)
}
}
impl<T> RightItem<T> {
pub(crate) fn extract(self) -> T {
self.value
}
}
impl<T: Hash> Hash for RightItem<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.value.hash(state)
}
}
impl<T: PartialEq> PartialEq for RightItem<T> {
fn eq(&self, other: &Self) -> bool {
self.id.eq(&other.id) && self.value.eq(&other.value)
}
}
impl<T: Eq> Eq for RightItem<T> {}
impl<T: Clone> Clone for RightItem<T> {
fn clone(&self) -> Self {
Self {
value: self.value.clone(),
pairs: self.pairs.clone(),
id: self.id,
}
}
}
impl<T: fmt::Debug> fmt::Debug for RightItem<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"RightItem {{ value: {:?}, id: {}, pairs: {:?} }}",
self.value, self.id.0, self.pairs
)
}
}
impl AddAssign<u64> for ID {
fn add_assign(&mut self, other: u64) {
self.0 += other;
}
}