use std::borrow::Borrow;
use std::cmp::Ordering;
use std::collections::HashSet as Inner;
use std::fmt;
use std::hash::Hash;
use std::sync::Arc;
use get_size::GetSize;
use get_size_derive::*;
use super::list::List;
pub struct Drain<'a, T> {
inner: &'a mut Inner<Arc<T>>,
order: super::list::Drain<'a, Arc<T>>,
}
impl<'a, T> Iterator for Drain<'a, T>
where
T: Eq + Hash + fmt::Debug,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let item = self.order.next()?;
self.inner.remove(&*item);
Some(Arc::try_unwrap(item).expect("item"))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.order.size_hint()
}
}
impl<'a, T> DoubleEndedIterator for Drain<'a, T>
where
T: Eq + Hash + fmt::Debug,
{
fn next_back(&mut self) -> Option<Self::Item> {
let item = self.order.next_back()?;
self.inner.remove(&*item);
Some(Arc::try_unwrap(item).expect("item"))
}
}
pub struct DrainWhile<'a, T, Cond> {
inner: &'a mut Inner<Arc<T>>,
order: &'a mut List<Arc<T>>,
cond: Cond,
}
impl<'a, T, Cond> Iterator for DrainWhile<'a, T, Cond>
where
T: Eq + Hash + fmt::Debug,
Cond: Fn(&T) -> bool,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if (self.cond)(self.order.front()?) {
let item = self.order.pop_front().expect("item");
self.inner.remove(&*item);
Some(Arc::try_unwrap(item).expect("item"))
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(self.inner.len()))
}
}
pub struct IntoIter<T> {
inner: super::list::IntoIter<Arc<T>>,
}
impl<T: fmt::Debug> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.inner
.next()
.map(|item| Arc::try_unwrap(item).expect("item"))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<T: fmt::Debug> DoubleEndedIterator for IntoIter<T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.inner
.next_back()
.map(|item| Arc::try_unwrap(item).expect("item"))
}
}
pub struct Iter<'a, T> {
inner: super::list::Iter<'a, Arc<T>>,
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|item| &**item)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back().map(|item| &**item)
}
}
#[derive(GetSize)]
pub struct OrdHashSet<T> {
inner: Inner<Arc<T>>,
order: List<Arc<T>>,
}
impl<T: Clone + Eq + Hash + Ord + fmt::Debug> Clone for OrdHashSet<T> {
fn clone(&self) -> Self {
self.iter().cloned().collect()
}
}
impl<T: PartialEq + fmt::Debug> PartialEq for OrdHashSet<T> {
fn eq(&self, other: &Self) -> bool {
self.order == other.order
}
}
impl<T: Eq + fmt::Debug> Eq for OrdHashSet<T> {}
impl<T> OrdHashSet<T> {
pub fn new() -> Self {
Self {
inner: Inner::new(),
order: List::new(),
}
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
inner: Inner::with_capacity(capacity),
order: List::with_capacity(capacity),
}
}
pub fn iter(&self) -> Iter<T> {
Iter {
inner: self.order.iter(),
}
}
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
pub fn len(&self) -> usize {
self.inner.len()
}
}
impl<T: Eq + Hash + Ord> OrdHashSet<T> {
fn bisect_hi<Cmp>(&self, cmp: Cmp) -> usize
where
Cmp: Fn(&T) -> Option<Ordering>,
{
if self.is_empty() {
return 0;
} else if cmp(self.order.back().expect("tail")).is_some() {
return self.len();
}
let mut lo = 0;
let mut hi = self.len();
while lo < hi {
let mid = (lo + hi) >> 1;
let item = self.order.get(mid).expect("item");
if cmp(&**item).is_some() {
lo = mid + 1;
} else {
hi = mid;
}
}
hi
}
fn bisect_lo<Cmp>(&self, cmp: Cmp) -> usize
where
Cmp: Fn(&T) -> Option<Ordering>,
{
if self.is_empty() {
return 0;
} else if cmp(self.order.front().expect("head")).is_some() {
return 0;
}
let mut lo = 0;
let mut hi = 1;
while lo < hi {
let mid = (lo + hi) >> 1;
let item = self.order.get(mid).expect("item");
if cmp(&**item).is_some() {
hi = mid;
} else {
lo = mid + 1;
}
}
hi
}
fn bisect_inner<Cmp>(&self, cmp: Cmp, mut lo: usize, mut hi: usize) -> Option<&T>
where
Cmp: Fn(&T) -> Option<Ordering>,
{
while lo < hi {
let mid = (lo + hi) >> 1;
let item = self.order.get(mid).expect("item");
if let Some(order) = cmp(&**item) {
match order {
Ordering::Less => hi = mid,
Ordering::Equal => return Some(item),
Ordering::Greater => lo = mid + 1,
}
} else {
panic!("comparison does not match distribution")
}
}
None
}
pub fn bisect<Cmp>(&self, cmp: Cmp) -> Option<&T>
where
Cmp: Fn(&T) -> Option<Ordering> + Copy,
{
let lo = self.bisect_lo(cmp);
let hi = self.bisect_hi(cmp);
self.bisect_inner(cmp, lo, hi)
}
pub fn bisect_and_remove<Cmp>(&mut self, cmp: Cmp) -> Option<T>
where
Cmp: Fn(&T) -> Option<Ordering> + Copy,
T: fmt::Debug,
{
let mut lo = self.bisect_lo(cmp);
let mut hi = self.bisect_hi(cmp);
let item = loop {
if lo >= hi {
break None;
}
let mid = (lo + hi) >> 1;
let item = self.order.get(mid).expect("item");
if let Some(order) = cmp(&**item) {
match order {
Ordering::Less => hi = mid,
Ordering::Equal => {
lo = mid;
break Some(item.clone());
}
Ordering::Greater => lo = mid + 1,
}
} else {
panic!("comparison does not match distribution")
}
}?;
self.order.remove(lo);
self.inner.remove(&item);
Some(Arc::try_unwrap(item).expect("item"))
}
pub fn clear(&mut self) {
self.inner.clear();
self.order.clear();
}
pub fn contains<Q: ?Sized>(&self, item: &Q) -> bool
where
Arc<T>: Borrow<Q>,
Q: Hash + Eq,
{
self.inner.contains(item)
}
pub fn drain(&mut self) -> Drain<T> {
Drain {
inner: &mut self.inner,
order: self.order.drain(),
}
}
pub fn drain_while<Cond>(&mut self, cond: Cond) -> DrainWhile<T, Cond>
where
Cond: Fn(&T) -> bool,
{
DrainWhile {
inner: &mut self.inner,
order: &mut self.order,
cond,
}
}
pub fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for item in iter {
self.insert(item);
}
}
pub fn first(&self) -> Option<&T> {
self.order.front().map(|item| &**item)
}
pub fn insert(&mut self, item: T) -> bool {
let new = if self.inner.contains(&item) {
false
} else {
let item = Arc::new(item);
let index = bisect(&self.order, &item);
if index == self.len() {
self.order.insert(index, item.clone());
} else {
let prior = self.order.get(index).expect("item").clone();
if &prior < &item {
self.order.insert(index + 1, item.clone());
} else {
self.order.insert(index, item.clone());
}
}
self.inner.insert(item)
};
new
}
pub fn last(&self) -> Option<&T> {
self.order.back().map(|item| &**item)
}
pub fn pop_first(&mut self) -> Option<T>
where
T: fmt::Debug,
{
if let Some(item) = self.order.pop_front() {
self.inner.remove(&item);
Some(Arc::try_unwrap(item).expect("item"))
} else {
None
}
}
pub fn pop_last(&mut self) -> Option<T>
where
T: fmt::Debug,
{
if let Some(item) = self.order.pop_back() {
self.inner.remove(&item);
Some(Arc::try_unwrap(item).expect("item"))
} else {
None
}
}
pub fn remove<Q>(&mut self, item: &Q) -> bool
where
Arc<T>: Borrow<Q>,
Q: Eq + Hash + Ord,
{
if self.inner.remove(item) {
let index = bisect(&self.order, item);
assert!(self.order.remove(index).expect("removed").borrow() == item);
true
} else {
false
}
}
pub fn starts_with<'a, I: IntoIterator<Item = &'a T>>(&'a self, other: I) -> bool
where
T: PartialEq,
{
let mut this = self.iter();
let mut that = other.into_iter();
while let Some(item) = that.next() {
if this.next() != Some(item) {
return false;
}
}
true
}
}
impl<T: Eq + Hash + Ord + fmt::Debug> OrdHashSet<T> {
#[allow(unused)]
fn is_valid(&self) -> bool {
assert_eq!(self.inner.len(), self.order.len());
if self.is_empty() {
return true;
}
let mut item = self.order.get(0).expect("item");
for i in 1..self.len() {
let next = self.order.get(i).expect("next");
assert!(*item <= *next, "set out of order: {:?}", self);
assert!(*next >= *item);
item = next;
}
true
}
}
impl<T: Eq + Hash + Ord + fmt::Debug> fmt::Debug for OrdHashSet<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("[ ")?;
for item in self {
write!(f, "{:?} ", item)?;
}
f.write_str("]")
}
}
impl<T: Eq + Hash + Ord + fmt::Debug> FromIterator<T> for OrdHashSet<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let iter = iter.into_iter();
let mut set = match iter.size_hint() {
(_, Some(max)) => Self::with_capacity(max),
(min, None) if min > 0 => Self::with_capacity(min),
_ => Self::new(),
};
set.extend(iter);
set
}
}
impl<T: fmt::Debug> IntoIterator for OrdHashSet<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
inner: self.order.into_iter(),
}
}
}
impl<'a, T> IntoIterator for &'a OrdHashSet<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
OrdHashSet::iter(self)
}
}
#[inline]
fn bisect<T, Q>(list: &List<T>, target: &Q) -> usize
where
T: Borrow<Q> + Ord,
Q: Ord,
{
if let Some(front) = list.front() {
if target < (*front).borrow() {
return 0;
}
}
if let Some(last) = list.back() {
if target > (*last).borrow() {
return list.len();
}
}
let mut lo = 0;
let mut hi = list.len();
while lo < hi {
let mid = (lo + hi) >> 1;
let item = &*list.get(mid).expect("item");
match item.borrow().cmp(target) {
Ordering::Less => lo = mid + 1,
Ordering::Greater => hi = mid,
Ordering::Equal => return mid,
}
}
lo
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bisect_and_remove() {
let mut set = OrdHashSet::<u8>::new();
assert!(set.bisect_and_remove(|item| item.partial_cmp(&8)).is_none());
set.insert(8);
assert!(set.bisect_and_remove(|item| item.partial_cmp(&8)).is_some());
assert!(set.bisect_and_remove(|item| item.partial_cmp(&8)).is_none());
set.insert(9);
assert!(set.bisect_and_remove(|item| item.partial_cmp(&8)).is_none());
set.insert(7);
assert!(set.bisect_and_remove(|item| item.partial_cmp(&8)).is_none());
}
#[test]
fn test_into_iter() {
let mut set = OrdHashSet::new();
assert!(set.insert("d"));
assert!(set.insert("a"));
assert!(set.insert("c"));
assert!(set.insert("b"));
assert!(!set.insert("a"));
assert_eq!(set.len(), 4);
assert_eq!(set.into_iter().collect::<Vec<&str>>(), ["a", "b", "c", "d"]);
}
#[test]
fn test_drain() {
let mut set = OrdHashSet::from_iter(0..10);
let expected = (0..10).into_iter().collect::<Vec<_>>();
let actual = set.drain().collect::<Vec<_>>();
assert_eq!(expected, actual);
}
#[test]
fn test_drain_while() {
let mut set = OrdHashSet::from_iter(0..10);
let drained = set.drain_while(|x| *x < 5).collect::<Vec<_>>();
assert_eq!(drained, vec![0, 1, 2, 3, 4]);
assert_eq!(set, OrdHashSet::from_iter(5..10));
}
}