90 lines
1.9 KiB
Rust
90 lines
1.9 KiB
Rust
pub trait TransposableIterator: Iterator {
|
|
fn transpose<C, J, T>(self) -> Transpose<Self>
|
|
where Self: Iterator<Item = C> + Clone + Sized,
|
|
C: IntoIterator<Item = T, IntoIter = J>,
|
|
J: ExactSizeIterator<Item = T>
|
|
{
|
|
Transpose::new(self)
|
|
}
|
|
}
|
|
|
|
impl<I> TransposableIterator for I where I: Iterator
|
|
{}
|
|
|
|
#[derive(Clone)]
|
|
pub struct Transpose<I> {
|
|
loc: ::std::ops::Range<usize>,
|
|
iter: I,
|
|
}
|
|
|
|
impl<I, C, J, T> Transpose<I>
|
|
where I: Iterator<Item = C> + Clone,
|
|
C: IntoIterator<Item = T, IntoIter = J>,
|
|
J: ExactSizeIterator<Item = T>
|
|
{
|
|
fn new(base: I) -> Transpose<I> {
|
|
let longest = base.clone()
|
|
.fold(0, |len, row| ::std::cmp::max(len, row.into_iter().len()));
|
|
|
|
Transpose {
|
|
loc: 0..longest,
|
|
iter: base,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<I> Iterator for Transpose<I> where I: Clone
|
|
{
|
|
type Item = TransposeInner<I>;
|
|
|
|
#[inline]
|
|
fn next(&mut self) -> Option<TransposeInner<I>> {
|
|
self.loc.next().map(|idx| {
|
|
TransposeInner {
|
|
iter: self.iter.clone(),
|
|
col: idx,
|
|
}
|
|
})
|
|
}
|
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
(self.loc.end, Some(self.loc.end))
|
|
}
|
|
}
|
|
|
|
impl<I> ExactSizeIterator for Transpose<I> where I: Clone
|
|
{}
|
|
|
|
impl<I> DoubleEndedIterator for Transpose<I> where I: Clone
|
|
{
|
|
fn next_back(&mut self) -> Option<TransposeInner<I>> {
|
|
self.loc.next_back().map(|idx| {
|
|
TransposeInner {
|
|
iter: self.iter.clone(),
|
|
col: idx,
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
|
#[derive(Clone)]
|
|
pub struct TransposeInner<I> {
|
|
iter: I,
|
|
col: usize,
|
|
}
|
|
|
|
impl<I, J, T> Iterator for TransposeInner<I>
|
|
where I: Iterator<Item = J>,
|
|
J: IntoIterator<Item = T>
|
|
{
|
|
type Item = T;
|
|
|
|
#[inline]
|
|
fn next(&mut self) -> Option<T> {
|
|
self.iter.next().and_then(|row| row.into_iter().nth(self.col))
|
|
}
|
|
}
|
|
|
|
// TODO: ExactSizeIterator and DoubleEndedIterator for TransposeInner
|