use std::{
borrow::Borrow,
default::Default,
fmt,
hash::{BuildHasher, Hash},
iter::FusedIterator,
marker::PhantomData,
};
use core::mem;
use hashbrown::{
hash_map::DefaultHashBuilder,
raw::{RawDrain, RawIter, RawTable},
TryReserveError,
};
use crate::{optionals::*, utils::*};
use OptionalPair::*;
#[cfg(doc)]
use crate::CycleMap;
pub(crate) struct MappingPair<T> {
pub(crate) value: T,
pub(crate) hash: Option<u64>,
pub(crate) id: u64,
}
pub(crate) fn equivalent_key<K, Q: PartialEq<K> + ?Sized>(
k: &Q,
) -> impl Fn(&MappingPair<K>) -> bool + '_ {
move |x| k.eq(&x.value)
}
pub(crate) fn hash_and_id<'a, Q: PartialEq + ?Sized>(
hash: u64,
id: u64,
) -> impl Fn(&MappingPair<Q>) -> bool + 'a {
move |x| id == x.id && Some(hash) == x.hash
}
pub(crate) fn just_id<'a, Q: PartialEq + ?Sized>(id: u64) -> impl Fn(&MappingPair<Q>) -> bool + 'a {
move |x| id == x.id
}
pub struct PartialCycleMap<L, R, St = DefaultHashBuilder> {
pub(crate) hash_builder: St,
pub(crate) counter: u64,
left_set: RawTable<MappingPair<L>>,
right_set: RawTable<MappingPair<R>>,
}
impl<L, R> PartialCycleMap<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> PartialCycleMap<L, R, S>
where
L: Eq + Hash,
R: Eq + Hash,
S: BuildHasher,
{
pub fn insert(&mut self, left: L, right: R) -> (OptionalPair<L, R>, OptionalPair<L, R>) {
let opt_from_left = self.remove_via_left(&left);
let opt_from_right = self.remove_via_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_pairing = MappingPair {
value: left,
hash: Some(r_hash),
id: self.counter,
};
let right_pairing = MappingPair {
value: right,
hash: Some(l_hash),
id: self.counter,
};
self.counter += 1;
self.left_set.insert(
l_hash,
left_pairing,
make_hasher::<MappingPair<L>, S>(&self.hash_builder),
);
self.right_set.insert(
r_hash,
right_pairing,
make_hasher::<MappingPair<R>, S>(&self.hash_builder),
);
digest
}
pub fn insert_left(&mut self, left: L) -> OptionalPair<L, R> {
let opt_from_left = self.remove_via_left(&left);
let digest = opt_from_left;
let l_hash = make_hash::<L, S>(&self.hash_builder, &left);
let left_pairing = MappingPair {
value: left,
hash: None,
id: self.counter,
};
self.counter += 1;
self.left_set.insert(
l_hash,
left_pairing,
make_hasher::<MappingPair<L>, S>(&self.hash_builder),
);
digest
}
pub fn insert_right(&mut self, right: R) -> OptionalPair<L, R> {
let opt_from_right = self.remove_via_right(&right);
let digest = opt_from_right;
let r_hash = make_hash::<R, S>(&self.hash_builder, &right);
let right_pairing = MappingPair {
value: right,
hash: None,
id: self.counter,
};
self.counter += 1;
self.right_set.insert(
r_hash,
right_pairing,
make_hasher::<MappingPair<R>, S>(&self.hash_builder),
);
digest
}
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));
let opt_right = self.right_set.get_mut(r_hash, equivalent_key(right));
match (opt_left, opt_right) {
(Some(left), Some(right)) => match (left.hash, right.hash) {
(None, None) => {
left.hash = Some(r_hash);
right.hash = Some(l_hash);
right.id = left.id;
true
}
_ => false,
},
_ => false,
}
}
pub fn pair_forced(&mut self, l: &L, r: &R) -> OptionalPair<&L, &R> {
if self.are_paired(l, r) {
return Neither;
}
let l_hash = make_hash::<L, S>(&self.hash_builder, l);
let r_hash = make_hash::<R, S>(&self.hash_builder, r);
let opt_left = self.left_set.get_mut(l_hash, equivalent_key(l));
let opt_right = self.right_set.get_mut(r_hash, equivalent_key(r));
match (opt_left, opt_right) {
(Some(left), Some(right)) => match (left.hash, right.hash) {
(None, None) => {
left.hash = Some(r_hash);
right.hash = Some(l_hash);
right.id = left.id;
Neither
}
(Some(lp_hash), None) => {
left.hash = Some(r_hash);
right.hash = Some(l_hash);
let old_id = left.id;
left.id = right.id;
self.right_set
.get_mut(lp_hash, hash_and_id(l_hash, old_id))
.unwrap()
.hash = None;
SomeRight(&self.right_set.get(lp_hash, just_id(old_id)).unwrap().value)
}
(None, Some(rp_hash)) => {
left.hash = Some(r_hash);
right.hash = Some(l_hash);
let old_id = right.id;
right.id = left.id;
self.left_set
.get_mut(rp_hash, hash_and_id(r_hash, old_id))
.unwrap()
.hash = None;
SomeLeft(&self.left_set.get(rp_hash, just_id(old_id)).unwrap().value)
}
(Some(lp_hash), Some(rp_hash)) => {
left.hash = Some(r_hash);
right.hash = Some(l_hash);
let old_l_id = left.id;
let old_r_id = right.id;
left.id = self.counter;
right.id = self.counter;
self.counter += 1;
self.left_set
.get_mut(rp_hash, hash_and_id(r_hash, old_r_id))
.unwrap()
.hash = None;
self.right_set
.get_mut(lp_hash, hash_and_id(l_hash, old_l_id))
.unwrap()
.hash = None;
SomeBoth(
&self.left_set.get(rp_hash, just_id(old_r_id)).unwrap().value,
&self
.right_set
.get(lp_hash, just_id(old_l_id))
.unwrap()
.value,
)
}
},
_ => Neither,
}
}
pub fn pair_forced_remove(&mut self, l: &L, r: &R) -> OptionalPair<L, R> {
if self.are_paired(l, r) {
return Neither;
}
let l_hash = make_hash::<L, S>(&self.hash_builder, l);
let r_hash = make_hash::<R, S>(&self.hash_builder, r);
let opt_left = self.left_set.get_mut(l_hash, equivalent_key(l));
let opt_right = self.right_set.get_mut(r_hash, equivalent_key(r));
match (opt_left, opt_right) {
(Some(left), Some(right)) => {
match (left.hash, right.hash) {
(None, None) => {
left.hash = Some(r_hash);
right.hash = Some(l_hash);
right.id = left.id;
Neither
}
(Some(lp_hash), None) => {
left.hash = Some(r_hash);
right.hash = Some(l_hash);
let old_id = left.id;
left.id = right.id;
SomeRight(
self.right_set
.remove_entry(lp_hash, just_id(old_id))
.unwrap()
.extract(),
)
}
(None, Some(rp_hash)) => {
left.hash = Some(r_hash);
right.hash = Some(l_hash);
let old_id = right.id;
right.id = left.id;
SomeLeft(
self.left_set
.remove_entry(rp_hash, hash_and_id(r_hash, old_id))
.unwrap()
.extract(),
)
}
(Some(lp_hash), Some(rp_hash)) => {
left.hash = Some(r_hash);
right.hash = Some(l_hash);
let old_l_id = left.id;
let old_r_id = right.id;
left.id = self.counter;
right.id = self.counter;
self.counter += 1;
SomeBoth(
self.left_set
.remove_entry(rp_hash, just_id(old_r_id))
.unwrap()
.extract(),
self.right_set
.remove_entry(lp_hash, just_id(old_l_id))
.unwrap()
.extract(),
)
}
}
}
_ => Neither,
}
}
pub fn unpair(&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));
let opt_right = self.right_set.get_mut(r_hash, equivalent_key(right));
match (opt_left, opt_right) {
(Some(left), Some(right)) => match (left.hash, right.hash) {
(Some(l_h), Some(r_h)) => {
if l_hash == r_h && r_hash == l_h {
left.hash = None;
right.hash = None;
right.id = self.counter;
self.counter += 1;
true
} else {
false
}
}
_ => false,
},
_ => false,
}
}
pub fn is_left_paired(&self, left: &L) -> bool {
let l_hash = make_hash::<L, S>(&self.hash_builder, left);
let opt_left = self.left_set.get(l_hash, equivalent_key(left));
match opt_left {
Some(l) => l.hash.is_some(),
None => false,
}
}
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));
match opt_right {
Some(r) => r.hash.is_some(),
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));
let opt_right = self.right_set.get(r_hash, equivalent_key(right));
match (opt_left, opt_right) {
(Some(left), Some(right)) => {
left.id == right.id && Some(l_hash) == right.hash && Some(r_hash) == left.hash
}
_ => 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)).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)).is_some()
}
pub fn remove(&mut self, left: &L, right: &R) -> Option<(L, R)> {
if self.are_paired(left, right) {
Option::from(self.remove_via_left(left))
.map(|(opt_l, opt_r)| (opt_l.unwrap(), opt_r.unwrap()))
} else {
None
}
}
pub fn remove_left(&mut self, item: &L) -> Option<L> {
let l_hash = make_hash::<L, S>(&self.hash_builder, item);
let item = self.left_set.remove_entry(l_hash, equivalent_key(item))?;
if let Some(hash) = item.hash {
self.right_set.get_mut(hash, just_id(item.id)).unwrap().hash = None;
}
Some(item.extract())
}
pub fn remove_via_left(&mut self, item: &L) -> OptionalPair<L, R> {
let l_hash = make_hash::<L, S>(&self.hash_builder, item);
let left_pairing: MappingPair<L> =
if let Some(p) = self.left_set.remove_entry(l_hash, equivalent_key(item)) {
p
} else {
return Neither;
};
let right_value: Option<R> = if let Some(hash) = left_pairing.hash {
Some(
self.right_set
.remove_entry(hash, hash_and_id(l_hash, left_pairing.id))
.unwrap()
.extract(),
)
} else {
None
};
OptionalPair::from((Some(left_pairing.extract()), right_value))
}
pub fn remove_right(&mut self, item: &R) -> Option<R> {
let r_hash = make_hash::<R, S>(&self.hash_builder, item);
let item = self.right_set.remove_entry(r_hash, equivalent_key(item))?;
if let Some(hash) = item.hash {
self.left_set.get_mut(hash, just_id(item.id)).unwrap().hash = None;
}
Some(item.extract())
}
pub fn remove_via_right(&mut self, item: &R) -> OptionalPair<L, R> {
let r_hash = make_hash::<R, S>(&self.hash_builder, item);
let right_pairing: MappingPair<R> =
if let Some(p) = self.right_set.remove_entry(r_hash, equivalent_key(item)) {
p
} else {
return Neither;
};
let left_value: Option<L> = if let Some(hash) = right_pairing.hash {
Some(
self.left_set
.remove_entry(hash, hash_and_id(r_hash, right_pairing.id))
.unwrap()
.extract(),
)
} else {
None
};
OptionalPair::from((left_value, Some(right_pairing.extract())))
}
fn remove_via_hashes_and_id(
&mut self,
l_hash: u64,
r_hash: u64,
id: u64,
) -> OptionalPair<L, R> {
let left_opt = self
.left_set
.remove_entry(l_hash, hash_and_id(r_hash, id))
.map(|opt_l| opt_l.extract());
let right_opt = self
.right_set
.remove_entry(r_hash, hash_and_id(l_hash, id))
.map(|opt_r| opt_r.extract());
OptionalPair::from((left_opt, right_opt))
}
pub fn swap_left(&mut self, old: &L, new: L) -> OptionalPair<L, OptionalPair<L, R>> {
let new_l_hash = make_hash::<L, S>(&self.hash_builder, &new);
let eq_opt = self.swap_left_eq_check(old, &new, new_l_hash);
let old_l_hash = make_hash::<L, S>(&self.hash_builder, old);
let l_pairing: &MappingPair<L> = match self.left_set.get(old_l_hash, equivalent_key(old)) {
Some(p) => p,
None => {
return Neither;
}
};
if let Some(hash) = l_pairing.hash {
let r_pairing: &mut MappingPair<R> = self
.right_set
.get_mut(hash, hash_and_id(old_l_hash, l_pairing.id))
.unwrap();
r_pairing.hash = Some(new_l_hash);
}
let new_left_pairing: MappingPair<L> = MappingPair {
value: new,
hash: l_pairing.hash,
id: l_pairing.id,
};
let old_left_item: L = self
.left_set
.remove_entry(old_l_hash, equivalent_key(old))
.unwrap()
.extract();
self.left_set.insert(
new_l_hash,
new_left_pairing,
make_hasher::<MappingPair<L>, S>(&self.hash_builder),
);
if eq_opt.is_none() {
SomeLeft(old_left_item)
} else {
SomeBoth(old_left_item, eq_opt)
}
}
pub fn swap_left_checked(
&mut self,
old: &L,
expected: &R,
new: L,
) -> OptionalPair<L, OptionalPair<L, R>> {
if !self.are_paired(old, expected) {
return Neither;
}
self.swap_left(old, new)
}
pub fn swap_left_or_insert(
&mut self,
old: &L,
new: L,
to_insert: R,
) -> OptionalPair<L, OptionalPair<L, R>> {
let old_l_hash = make_hash::<L, S>(&self.hash_builder, old);
if self.left_set.get(old_l_hash, equivalent_key(old)).is_some() {
self.swap_left(old, new)
} else {
match self.insert(new, to_insert) {
(Neither, Neither) => Neither,
(Neither, pair) => SomeRight(pair),
_ => {
unreachable!("There isn't a left item")
}
}
}
}
fn swap_left_eq_check(&mut self, old: &L, new: &L, new_hash: u64) -> OptionalPair<L, R> {
let opt = self.left_set.get(new_hash, equivalent_key(new));
if opt.is_some() && new != old {
self.remove_via_left(new)
} else {
Neither
}
}
pub fn swap_right(&mut self, old: &R, new: R) -> OptionalPair<R, OptionalPair<L, R>> {
let new_r_hash = make_hash::<R, S>(&self.hash_builder, &new);
let eq_opt = self.swap_right_eq_check(old, &new, new_r_hash);
let old_r_hash = make_hash::<R, S>(&self.hash_builder, old);
let r_pairing: &MappingPair<R> = match self.right_set.get(old_r_hash, equivalent_key(old)) {
Some(p) => p,
None => {
return Neither;
}
};
if let Some(hash) = r_pairing.hash {
let l_pairing: &mut MappingPair<L> = self
.left_set
.get_mut(hash, hash_and_id(old_r_hash, r_pairing.id))
.unwrap();
l_pairing.hash = Some(new_r_hash);
}
let new_right_pairing = MappingPair {
value: new,
hash: r_pairing.hash,
id: r_pairing.id,
};
let old_right_item: R = self
.right_set
.remove_entry(old_r_hash, equivalent_key(old))
.unwrap()
.extract();
self.right_set.insert(
new_r_hash,
new_right_pairing,
make_hasher::<MappingPair<R>, S>(&self.hash_builder),
);
if eq_opt.is_none() {
SomeLeft(old_right_item)
} else {
SomeBoth(old_right_item, eq_opt)
}
}
pub fn swap_right_checked(
&mut self,
old: &R,
expected: &L,
new: R,
) -> OptionalPair<R, OptionalPair<L, R>> {
if !self.are_paired(expected, old) {
return Neither;
} self.swap_right(old, new)
}
pub fn swap_right_or_insert(
&mut self,
old: &R,
new: R,
to_insert: L,
) -> OptionalPair<R, OptionalPair<L, R>> {
let old_r_hash = make_hash::<R, S>(&self.hash_builder, old);
if self
.right_set
.get(old_r_hash, equivalent_key(old))
.is_some()
{
self.swap_right(old, new)
} else {
match self.insert(to_insert, new) {
(Neither, Neither) => Neither,
(pair, Neither) => SomeRight(pair),
_ => {
unreachable!("There isn't a left item")
}
}
}
}
fn swap_right_eq_check(&mut self, old: &R, new: &R, new_hash: u64) -> OptionalPair<L, R> {
let opt = self.right_set.get(new_hash, equivalent_key(new));
if opt.is_some() && new != old {
self.remove_via_right(new)
} else {
Neither
}
}
pub fn get_left<Q>(&self, item: &Q) -> Option<&L>
where
R: Borrow<Q>,
Q: Hash + Eq + PartialEq<R>,
{
let r_hash = make_hash::<_, S>(&self.hash_builder, item);
let right_pairing: &MappingPair<R> = self.get_right_inner_with_hash(item, r_hash)?;
let hash = right_pairing.hash?;
match self
.left_set
.get(hash, hash_and_id(r_hash, right_pairing.id))
{
None => None,
Some(pairing) => Some(&pairing.value),
}
}
pub fn get_right<Q>(&self, item: &Q) -> Option<&R>
where
L: Borrow<Q>,
Q: Hash + Eq + PartialEq<L>,
{
let l_hash = make_hash::<_, S>(&self.hash_builder, item);
let left_pairing: &MappingPair<L> = self.get_left_inner_with_hash(item, l_hash)?;
let hash = left_pairing.hash?;
match self
.right_set
.get(hash, hash_and_id(l_hash, left_pairing.id))
{
None => None,
Some(pairing) => Some(&pairing.value),
}
}
fn get_via_hashes_and_id(&self, l_hash: u64, r_hash: u64, id: u64) -> Option<(&L, &R)> {
let left_pairing = self.left_set.get(l_hash, hash_and_id(r_hash, id))?;
let right_pairing = self.right_set.get(r_hash, hash_and_id(l_hash, id)).unwrap();
Some((&left_pairing.value, &right_pairing.value))
}
#[inline]
fn get_left_inner(&self, item: &L) -> Option<&MappingPair<L>> {
let hash = make_hash::<L, S>(&self.hash_builder, item);
self.left_set.get(hash, equivalent_key(item))
}
#[inline]
fn get_left_inner_with_hash<Q>(&self, item: &Q, hash: u64) -> Option<&MappingPair<L>>
where
L: Borrow<Q>,
Q: Hash + Eq + PartialEq<L>,
{
self.left_set.get(hash, equivalent_key(item))
}
#[inline]
fn get_right_inner(&self, item: &R) -> Option<&MappingPair<R>> {
let hash = make_hash::<R, S>(&self.hash_builder, item);
self.right_set.get(hash, equivalent_key(item))
}
#[inline]
fn get_right_inner_with_hash<Q>(&self, item: &Q, hash: u64) -> Option<&MappingPair<R>>
where
R: Borrow<Q>,
Q: Hash + Eq + PartialEq<R>,
{
self.right_set.get(hash, equivalent_key(item))
}
pub fn iter(&self) -> Iter<'_, L, R, S> {
Iter {
left_iter: unsafe { self.left_set.iter() },
map_ref: self,
}
}
pub fn iter_paired(&self) -> PairedIter<'_, L, R, S> {
PairedIter {
left_iter: unsafe { self.left_set.iter() },
right_iter: unsafe { self.right_set.iter() },
map_ref: self,
}
}
pub fn iter_unpaired(&self) -> UnpairedIter<'_, L, R, S> {
UnpairedIter {
left_iter: unsafe { self.left_set.iter() },
right_iter: unsafe { self.right_set.iter() },
map_ref: self,
}
}
pub fn iter_left(&self) -> SingleIter<'_, L> {
SingleIter {
iter: unsafe { self.left_set.iter() },
marker: PhantomData,
}
}
pub fn iter_right(&self) -> SingleIter<'_, R> {
SingleIter {
iter: unsafe { self.right_set.iter() },
marker: PhantomData,
}
}
pub fn drain(&mut self) -> DrainIter<'_, L, R> {
DrainIter {
left_iter: self.left_set.drain(),
right_ref: &mut self.right_set,
}
}
pub fn drain_filter<F>(&mut self, f: F) -> DrainFilterIter<'_, L, R, F>
where
F: FnMut(OptionalPair<&L, &R>) -> bool,
{
unsafe {
DrainFilterIter {
f,
inner: DrainFilterInner {
left_iter: self.left_set.iter(),
right_iter: self.right_set.iter(),
left_ref: &mut self.left_set,
right_ref: &mut self.right_set,
reset_right_iter: true,
},
}
}
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&OptionalPair<&L, &R>) -> bool,
{
let mut to_drop: Vec<(Option<u64>, Option<u64>, u64)> =
Vec::with_capacity(self.left_set.len());
for op in self.iter() {
if f(&op) {
let (left, right): (Option<&L>, Option<&R>) = op.into();
let l_hash = left.map(|l| make_hash::<L, S>(&self.hash_builder, l));
let r_hash = right.map(|r| make_hash::<R, S>(&self.hash_builder, r));
let id = if let Some(l) = left {
self.get_left_inner(l).unwrap().id
} else {
self.get_right_inner(right.unwrap()).unwrap().id
};
to_drop.push((l_hash, r_hash, id));
}
}
for tup in to_drop {
match tup {
(Some(l), Some(r), id) => {
self.remove_via_hashes_and_id(l, r, id);
}
(Some(l), None, id) => {
self.left_set.remove_entry(l, |p| p.id == id);
}
(None, Some(r), id) => {
self.right_set.remove_entry(r, |p| p.id == id);
}
_ => {
unreachable!("There is either some left or some right hash.");
}
}
}
}
pub fn retain_paired<F>(&mut self, mut f: F)
where
F: FnMut(&L, &R) -> bool,
{
let mut to_drop: Vec<(u64, u64, u64)> = Vec::with_capacity(self.left_set.len());
for (left, right) in self.iter_paired() {
if f(left, right) {
let l_hash = make_hash::<L, S>(&self.hash_builder, left);
let r_hash = make_hash::<R, S>(&self.hash_builder, right);
let id = self.get_left_inner(left).unwrap().id;
to_drop.push((l_hash, r_hash, id));
}
}
for (l_hash, r_hash, id) in to_drop {
self.remove_via_hashes_and_id(l_hash, r_hash, id);
}
}
pub fn retain_unpaired<F>(&mut self, mut f: F)
where
F: FnMut(&OptionalPair<&L, &R>) -> bool,
{
let mut to_drop: Vec<(Option<u64>, Option<u64>, u64)> =
Vec::with_capacity(self.left_set.len());
for op in self.iter_unpaired() {
if f(&op) {
match op {
SomeLeft(left) => {
let l_hash = make_hash::<L, S>(&self.hash_builder, left);
let id = self.get_left_inner_with_hash(left, l_hash).unwrap().id;
to_drop.push((Some(l_hash), None, id));
}
SomeRight(right) => {
let r_hash = make_hash::<R, S>(&self.hash_builder, right);
let id = self.get_right_inner_with_hash(right, r_hash).unwrap().id;
to_drop.push((None, Some(r_hash), id));
}
_ => {
unreachable!("We are only iterating over unpaired items.");
}
}
}
}
for tup in to_drop {
match tup {
(Some(l), None, id) => {
self.left_set.remove_entry(l, |p| p.id == id);
}
(None, Some(r), id) => {
self.right_set.remove_entry(r, |p| p.id == id);
}
_ => {
unreachable!("We are only iterating over unpaired items.");
}
}
}
}
pub fn shrink_to_left(&mut self, min_capacity: usize) {
self.left_set
.shrink_to(min_capacity, make_hasher(&self.hash_builder));
}
pub fn shrink_to_right(&mut self, min_capacity: usize) {
self.right_set
.shrink_to(min_capacity, make_hasher(&self.hash_builder));
}
pub fn shrink_to_fit(&mut self) {
self.left_set
.shrink_to(self.len_left(), make_hasher(&self.hash_builder));
self.right_set
.shrink_to(self.len_right(), make_hasher(&self.hash_builder));
}
pub fn reserve_left(&mut self, additional: usize) {
self.left_set
.reserve(additional, make_hasher(&self.hash_builder));
}
pub fn reserve_right(&mut self, additional: usize) {
self.right_set
.reserve(additional, make_hasher(&self.hash_builder));
}
pub fn try_reserve_left(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.left_set
.try_reserve(additional, make_hasher(&self.hash_builder))?;
Ok(())
}
pub fn try_reserve_right(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.right_set
.try_reserve(additional, make_hasher(&self.hash_builder))?;
Ok(())
}
}
impl<L, R, S> Clone for PartialCycleMap<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(),
counter: self.counter,
hash_builder: self.hash_builder.clone(),
}
}
}
impl<L, R, S> Default for PartialCycleMap<L, R, S>
where
S: Default,
{
fn default() -> Self {
Self::with_hasher(Default::default())
}
}
impl<L, R, S> fmt::Debug for PartialCycleMap<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<PartialCycleMap<L, R, S>> for PartialCycleMap<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(|op| match op {
SomeLeft(l) => other.get_right(l).is_none(),
SomeRight(r) => other.get_left(r).is_none(),
SomeBoth(l, r) => other.are_paired(l, r),
_ => {
unreachable!("There has to be at least one item.")
}
})
}
}
impl<L, R, S> Eq for PartialCycleMap<L, R, S>
where
L: Hash + Eq,
R: Hash + Eq,
S: BuildHasher,
{
}
impl<L, R, S> PartialCycleMap<L, R, S> {
pub const fn with_hasher(hash_builder: S) -> Self {
Self {
hash_builder,
counter: 0,
left_set: RawTable::new(),
right_set: RawTable::new(),
}
}
pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self {
Self {
hash_builder,
counter: 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<(L, R)> for PartialCycleMap<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 (l, r) in iter {
self.insert(l, r);
}
}
}
impl<L, R, S> Extend<OptionalPair<L, R>> for PartialCycleMap<L, R, S>
where
L: Hash + Eq,
R: Hash + Eq,
S: BuildHasher,
{
#[inline]
fn extend<T: IntoIterator<Item = OptionalPair<L, R>>>(&mut self, iter: T) {
for op in iter {
match op {
Neither => {}
SomeLeft(l) => {
self.insert_left(l);
}
SomeRight(r) => {
self.insert_right(r);
}
SomeBoth(l, r) => {
self.insert(l, r);
}
}
}
}
}
impl<L, R> FromIterator<(L, R)> for PartialCycleMap<L, R>
where
L: Hash + Eq,
R: Hash + Eq,
{
fn from_iter<T: IntoIterator<Item = (L, R)>>(iter: T) -> Self {
let mut digest = PartialCycleMap::default();
digest.extend(iter);
digest
}
}
impl<L, R> FromIterator<OptionalPair<L, R>> for PartialCycleMap<L, R>
where
L: Hash + Eq,
R: Hash + Eq,
{
fn from_iter<T: IntoIterator<Item = OptionalPair<L, R>>>(iter: T) -> Self {
let mut digest = PartialCycleMap::default();
digest.extend(iter);
digest
}
}
pub struct Iter<'a, L, R, S> {
left_iter: RawIter<MappingPair<L>>,
map_ref: &'a PartialCycleMap<L, R, S>,
}
impl<L, R, S> Clone for Iter<'_, 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 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 = OptionalPair<&'a L, &'a R>;
fn next(&mut self) -> Option<Self::Item> {
match self.left_iter.next() {
Some(l) => unsafe {
let left = &l.as_ref().value;
let right = self.map_ref.get_right(left);
Some(OptionalPair::from((Some(left), right)))
},
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.left_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<MappingPair<L>>,
right_iter: RawIter<MappingPair<R>>,
map_ref: &'a PartialCycleMap<L, R, S>,
}
impl<L, R, S> Clone for PairedIter<'_, L, R, S> {
fn clone(&self) -> Self {
Self {
left_iter: self.left_iter.clone(),
right_iter: self.right_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> {
for l_pairing in self.left_iter.by_ref() {
let l = unsafe { l_pairing.as_ref() };
if l.hash.is_none() {
continue;
}
let left = &l.value;
let l_hash = make_hash(self.map_ref.hasher(), left);
let id = l.id;
return self
.map_ref
.get_via_hashes_and_id(l_hash, l.hash.unwrap(), id);
}
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> {
left_iter: RawIter<MappingPair<L>>,
right_iter: RawIter<MappingPair<R>>,
map_ref: &'a PartialCycleMap<L, R, S>,
}
impl<L, R, S> Clone for UnpairedIter<'_, L, R, S> {
fn clone(&self) -> Self {
Self {
left_iter: self.left_iter.clone(),
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 = OptionalPair<&'a L, &'a R>;
fn next(&mut self) -> Option<Self::Item> {
for l_pairing in self.left_iter.by_ref() {
let l = unsafe { l_pairing.as_ref() };
if l.hash.is_some() {
continue;
}
return Some(SomeLeft(&l.value));
}
for r_pairing in self.right_iter.by_ref() {
let r = unsafe { r_pairing.as_ref() };
if r.hash.is_some() {
continue;
}
return Some(SomeRight(&r.value));
}
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.left_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 SingleIter<'a, T> {
iter: RawIter<MappingPair<T>>,
marker: PhantomData<&'a T>,
}
impl<T> Clone for SingleIter<'_, T> {
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
marker: PhantomData,
}
}
}
impl<T> fmt::Debug for SingleIter<'_, T>
where
T: Hash + Eq + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}
impl<'a, T> Iterator for SingleIter<'a, T>
where
T: 'a + Hash + Eq,
{
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
match self.iter.next() {
Some(item) => {
let val = unsafe { &item.as_ref().value };
Some(val)
}
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<T> ExactSizeIterator for SingleIter<'_, T>
where
T: Hash + Eq,
{
fn len(&self) -> usize {
self.iter.len()
}
}
impl<T> FusedIterator for SingleIter<'_, T> where T: Hash + Eq {}
#[allow(missing_debug_implementations)]
pub struct DrainIter<'a, L, R>
where
L: Eq + Hash,
R: Eq + Hash,
{
left_iter: RawDrain<'a, MappingPair<L>>,
right_ref: &'a mut RawTable<MappingPair<R>>,
}
impl<'a, L, R> Drop for DrainIter<'a, L, R>
where
L: Eq + Hash,
R: Eq + Hash,
{
fn drop(&mut self) {
while let Some(item) = self.next() {
let guard = ConsumeAllOnDrop(self);
drop(item);
mem::forget(guard);
}
}
}
pub(super) struct ConsumeAllOnDrop<'a, T: Iterator>(pub(super) &'a mut T);
impl<T: Iterator> Drop for ConsumeAllOnDrop<'_, T> {
fn drop(&mut self) {
self.0.for_each(drop)
}
}
impl<'a, L, R> Iterator for DrainIter<'a, L, R>
where
L: Hash + Eq,
R: Hash + Eq,
{
type Item = OptionalPair<L, R>;
fn next(&mut self) -> Option<Self::Item> {
match self.left_iter.next() {
Some(left) => match left.hash {
Some(hash) => {
let right = self
.right_ref
.remove_entry(hash, just_id(left.id))
.unwrap()
.extract();
Some(SomeBoth(left.extract(), right))
}
None => Some(SomeLeft(left.extract())),
},
None => self
.right_ref
.drain()
.next()
.map(|right| SomeRight(right.extract())),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.left_iter.size_hint()
}
}
impl<L, R> ExactSizeIterator for DrainIter<'_, L, R>
where
L: Hash + Eq,
R: Hash + Eq,
{
fn len(&self) -> usize {
self.left_iter.len()
}
}
impl<L, R> FusedIterator for DrainIter<'_, L, R>
where
L: Hash + Eq,
R: Hash + Eq,
{
}
#[allow(missing_debug_implementations)]
pub struct DrainFilterIter<'a, L, R, F>
where
L: Eq,
R: Eq,
F: FnMut(OptionalPair<&L, &R>) -> bool,
{
f: F,
inner: DrainFilterInner<'a, L, R>,
}
impl<'a, L, R, F> Drop for DrainFilterIter<'a, L, R, F>
where
L: Eq,
R: Eq,
F: FnMut(OptionalPair<&L, &R>) -> bool,
{
fn drop(&mut self) {
while let Some(item) = self.next() {
let guard = ConsumeAllOnDrop(self);
drop(item);
mem::forget(guard);
}
}
}
impl<L: Eq, R: Eq, F> Iterator for DrainFilterIter<'_, L, R, F>
where
F: FnMut(OptionalPair<&L, &R>) -> bool,
{
type Item = OptionalPair<L, R>;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next(&mut self.f)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, self.inner.left_iter.size_hint().1)
}
}
impl<L: Eq, R: Eq, F> FusedIterator for DrainFilterIter<'_, L, R, F> where
F: FnMut(OptionalPair<&L, &R>) -> bool
{
}
pub(super) struct DrainFilterInner<'a, L, R> {
pub(super) left_iter: RawIter<MappingPair<L>>,
pub(super) right_iter: RawIter<MappingPair<R>>,
pub(super) left_ref: &'a mut RawTable<MappingPair<L>>,
pub(super) right_ref: &'a mut RawTable<MappingPair<R>>,
pub(super) reset_right_iter: bool,
}
impl<L: Eq, R: Eq> DrainFilterInner<'_, L, R> {
pub(super) fn next<F>(&mut self, f: &mut F) -> Option<OptionalPair<L, R>>
where
F: FnMut(OptionalPair<&L, &R>) -> bool,
{
for left in self.left_iter.by_ref() {
let l_pairing = unsafe { left.as_ref() };
match l_pairing.hash {
Some(hash) => {
let right = self.right_ref.find(hash, just_id(l_pairing.id)).unwrap();
if unsafe { f(SomeBoth(&l_pairing.value, &right.as_ref().value)) } {
let l = unsafe { self.left_ref.remove(left).extract() };
let r = unsafe { self.right_ref.remove(right).extract() };
return Some(SomeBoth(l, r));
}
}
None => {
if f(SomeLeft(&l_pairing.value)) {
let l = unsafe { self.left_ref.remove(left).extract() };
return Some(SomeLeft(l));
}
}
}
}
if self.reset_right_iter {
self.right_iter = unsafe { self.right_ref.iter() };
self.reset_right_iter = false;
}
for right in self.right_iter.by_ref() {
let r_pairing = unsafe { right.as_ref() };
if f(SomeRight(&r_pairing.value)) {
let r = unsafe { self.right_ref.remove(right).extract() };
return Some(SomeRight(r));
}
}
None
}
}
impl<T> MappingPair<T> {
pub(crate) fn extract(self) -> T {
self.value
}
}
impl<T: Hash> Hash for MappingPair<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.value.hash(state)
}
}
impl<T: PartialEq> PartialEq for MappingPair<T> {
fn eq(&self, other: &Self) -> bool {
self.id.eq(&other.id) && self.value.eq(&other.value)
}
}
impl<T: PartialEq> PartialEq<T> for MappingPair<T> {
fn eq(&self, other: &T) -> bool {
self.value.eq(other)
}
}
impl<T: Eq> Eq for MappingPair<T> {}
impl<T: Clone> Clone for MappingPair<T> {
fn clone(&self) -> Self {
Self {
value: self.value.clone(),
hash: self.hash,
id: self.id,
}
}
}
impl<T: fmt::Debug> fmt::Debug for MappingPair<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"MappingPair {{ value: {:?}, hash: {:?}, id: {} }}",
self.value, self.hash, self.id
)
}
}