|
|
|
@ -1,4 +1,6 @@
|
|
|
|
|
use std::iter::FusedIterator;
|
|
|
|
|
use std::collections::BTreeSet;
|
|
|
|
|
use std::borrow::Borrow;
|
|
|
|
|
|
|
|
|
|
/// An iterator that may be empty.
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
@ -67,4 +69,94 @@ where I: Iterator<Item=T> + DoubleEndedIterator
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// An iterator that deduplicates an iterator over references by pointer identity.
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct DedupedRefIter<'a, I, T: ?Sized + 'a>(I, BTreeSet<*const T>)
|
|
|
|
|
where I: Iterator<Item = &'a T>;
|
|
|
|
|
|
|
|
|
|
pub trait DedupIterExt<'a, I, T: ?Sized + 'a>
|
|
|
|
|
where I: Iterator<Item = &'a T>
|
|
|
|
|
{
|
|
|
|
|
/// Deduplicate this iterator by pointer identity.
|
|
|
|
|
fn dedup_ref(self) -> DedupedRefIter<'a, I, T>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a, I, T:?Sized+'a, IntoIter> DedupIterExt<'a, I, T> for IntoIter
|
|
|
|
|
where IntoIter: IntoIterator<IntoIter=I>,
|
|
|
|
|
I: Iterator<Item= &'a T>
|
|
|
|
|
{
|
|
|
|
|
fn dedup_ref(self) -> DedupedRefIter<'a, I, T> {
|
|
|
|
|
DedupedRefIter(self.into_iter(), BTreeSet::new())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a, I, T:?Sized + 'a> Iterator for DedupedRefIter<'a, I, T>
|
|
|
|
|
where I: Iterator<Item = &'a T>
|
|
|
|
|
{
|
|
|
|
|
type Item = &'a T;
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item>
|
|
|
|
|
{
|
|
|
|
|
Some(loop {
|
|
|
|
|
if let Some(next) = self.0.next()
|
|
|
|
|
{
|
|
|
|
|
if self.1.insert(next as *const T) {
|
|
|
|
|
break next;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
|
|
|
match self.0.size_hint()
|
|
|
|
|
{
|
|
|
|
|
(0, h) => (0, h),
|
|
|
|
|
(_, h) => (1, h),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a, I, T:?Sized + 'a> DoubleEndedIterator for DedupedRefIter<'a, I, T>
|
|
|
|
|
where I: Iterator<Item = &'a T> + DoubleEndedIterator
|
|
|
|
|
{
|
|
|
|
|
fn next_back(&mut self) -> Option<Self::Item> {
|
|
|
|
|
Some(loop {
|
|
|
|
|
if let Some(next) = self.0.next_back()
|
|
|
|
|
{
|
|
|
|
|
if self.1.insert(next as *const T) {
|
|
|
|
|
break next;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a, I, T:?Sized + 'a> FusedIterator for DedupedRefIter<'a, I, T>
|
|
|
|
|
where I: Iterator<Item = &'a T> + FusedIterator{}
|
|
|
|
|
|
|
|
|
|
pub trait ContainsAllExt<T, U, I>
|
|
|
|
|
where U: AsRef<T>,
|
|
|
|
|
I: IntoIterator<Item = U>,
|
|
|
|
|
{
|
|
|
|
|
fn contains_all(&self, items: I) -> bool;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T, U, S, I> ContainsAllExt<T, U, I> for S
|
|
|
|
|
where S: AsRef<[T]>,
|
|
|
|
|
U: AsRef<T>,
|
|
|
|
|
I: IntoIterator<Item = U>,
|
|
|
|
|
T: PartialEq,
|
|
|
|
|
{
|
|
|
|
|
fn contains_all(&self, items: I) -> bool {
|
|
|
|
|
for x in items.into_iter()
|
|
|
|
|
{
|
|
|
|
|
if !self.as_ref().contains(x.as_ref()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|