You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
3.5 KiB

use super::*;
/// An iterator that may be empty.
#[derive(Debug, Clone)]
pub struct MaybeIter<I, T>(Option<I>)
where I: Iterator<Item=T>;
pub trait OptionIterExt<I, T>: Sized
where I: Iterator<Item=T>
{
/// Map this `Option<Iterator>` into an iterator that will yield the items of the iterator if it is present.
fn map_into_iter(self) -> MaybeIter<I, T>;
}
impl<E, T, I, Into: IntoIterator<IntoIter=I, Item=T>> OptionIterExt<I, T> for Result<Into, E>
where I: Iterator<Item = T>
{
#[inline] fn map_into_iter(self) -> MaybeIter<I, T> {
MaybeIter(self.ok().map(|x| x.into_iter()))
}
}
impl<T, I, Into: IntoIterator<IntoIter=I, Item=T>> OptionIterExt<I, T> for Option<Into>
where I: Iterator<Item = T>
{
#[inline] fn map_into_iter(self) -> MaybeIter<I, T> {
MaybeIter(self.map(|x| x.into_iter()))
}
}
impl<I, T> Iterator for MaybeIter<I, T>
where I: Iterator<Item=T>
{
type Item = T;
fn next(&mut self) -> Option<Self::Item>
{
if let Some(ref mut iter) = self.0
{
iter.next()
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
match &self.0 {
Some(i) => i.size_hint(),
None => (0, Some(0)),
}
}
}
impl<I, T> FusedIterator for MaybeIter<I, T>
where I: Iterator<Item=T> + FusedIterator{}
impl<I, T> ExactSizeIterator for MaybeIter<I, T>
where I: Iterator<Item=T> + ExactSizeIterator{}
impl<I, T> DoubleEndedIterator for MaybeIter<I, T>
where I: Iterator<Item=T> + DoubleEndedIterator
{
fn next_back(&mut self) -> Option<Self::Item> {
if let Some(ref mut iter) = self.0
{
iter.next_back()
} else {
None
}
}
}
/// 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>
{
fn contains_all<V: AsRef<[T]>>(&self, items: V) -> bool;
}
impl<T, S> ContainsAllExt<T> for S
where S: AsRef<[T]>,
T: PartialEq,
{
fn contains_all<V: AsRef<[T]>>(&self, items: V) -> bool {
let s = self.as_ref();
for x in items.as_ref().iter()
{
if !s.contains(x) {
return false;
}
}
true
}
}