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.
265 lines
5.6 KiB
265 lines
5.6 KiB
use super::*;
|
|
use std::iter::Fuse;
|
|
use std::marker::PhantomData;
|
|
|
|
/// 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
|
|
}
|
|
}
|
|
|
|
|
|
// Chunking iterator
|
|
|
|
/// A stream that chunks its input.
|
|
pub struct ChunkingIter<I, T, Into=Vec<T>>
|
|
{
|
|
stream: Fuse<I>,
|
|
buf: Vec<T>,
|
|
cap: usize,
|
|
_output: PhantomData<Into>,
|
|
|
|
push_now: bool,
|
|
}
|
|
|
|
|
|
impl<S, T, Into> ChunkingIter<S,T, Into>
|
|
where S: Iterator<Item=T>,
|
|
Into: From<Vec<T>>
|
|
{
|
|
/// Create a new chunking iterator with this chunk size.
|
|
pub fn new(stream: S, sz: usize) -> Self
|
|
{
|
|
Self {
|
|
stream: stream.fuse(),
|
|
buf: Vec::with_capacity(sz),
|
|
cap: sz,
|
|
_output: PhantomData,
|
|
push_now: false,
|
|
}
|
|
}
|
|
pub fn into_inner(self) -> Fuse<S>
|
|
{
|
|
self.stream
|
|
}
|
|
pub fn cap(&self) -> usize
|
|
{
|
|
self.cap
|
|
}
|
|
pub fn buffer(&self) -> &[T]
|
|
{
|
|
&self.buf[..]
|
|
}
|
|
|
|
pub fn get_ref(&self) -> &Fuse<S>
|
|
{
|
|
&self.stream
|
|
}
|
|
|
|
pub fn get_mut(&mut self)-> &mut Fuse<S>
|
|
{
|
|
&mut self.stream
|
|
}
|
|
|
|
/// Force the next read to send the buffer even if it's not full.
|
|
///
|
|
/// # Note
|
|
/// The buffer still won't send if it's empty.
|
|
pub fn push_now(&mut self)
|
|
{
|
|
self.push_now= true;
|
|
}
|
|
|
|
/// Consume into the current held buffer
|
|
pub fn into_buffer(self) -> Vec<T>
|
|
{
|
|
self.buf
|
|
}
|
|
|
|
/// Take the buffer now
|
|
pub fn take_now(&mut self) -> Into
|
|
{
|
|
std::mem::replace(&mut self.buf, Vec::with_capacity(self.cap)).into()
|
|
}
|
|
}
|
|
|
|
impl<S, T, Into> Iterator for ChunkingIter<S,T, Into>
|
|
where S: Iterator<Item=T>,
|
|
Into: From<Vec<T>>
|
|
{
|
|
type Item = Into;
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
while !(self.push_now && !self.buf.is_empty()) && self.buf.len() < self.cap {
|
|
// Buffer isn't full, keep filling
|
|
match self.stream.next() {
|
|
None => {
|
|
// Stream is over
|
|
break;
|
|
},
|
|
Some(item) => {
|
|
self.buf.push(item);
|
|
},
|
|
}
|
|
}
|
|
|
|
// Buffer is full or we reach end of iter
|
|
if self.buf.len() == 0 {
|
|
None
|
|
} else {
|
|
self.push_now = false;
|
|
let output = std::mem::replace(&mut self.buf, Vec::with_capacity(self.cap));
|
|
Some(output.into())
|
|
}
|
|
}
|
|
}
|