I'm trying to write an iterator that receives an array of "column" iterators and interleaves the columns into an iterator over rows. The rows themselves should be iterators. The goal is to avoid allocating intermediate vectors, but I'm trying to figure out if it's possible to also avoid the Rc<RefCell<_>>
.
It would also be nice to avoid peeking the row iterator in the loop.
struct Transpose<'a, I>
where
I: Iterator,
I::Item: 'a,
{
iters: Rc<RefCell<Vec<I>>>,
row: Row<'a, I>,
}
impl<'a, I> Transpose<'a, I>
where
I: Iterator,
I::Item: 'a,
{
fn new(iters: Rc<RefCell<Vec<I>>>) -> Self {
Self {
row: Row::new(Rc::clone(&iters)),
iters,
}
}
fn next(&mut self) -> Option<&mut Row<'a, I>> {
if self.row.empty {
return None;
}
self.row = Row::new(Rc::clone(&self.iters));
Some(&mut self.row)
}
}
pub struct Row<'a, I>
where
I: Iterator,
I::Item: 'a,
{
index: usize,
empty: bool,
iters: Rc<RefCell<Vec<I>>>,
phantom: PhantomData<&'a I>,
}
impl<'a, I> Row<'a, I>
where
I: Iterator,
I::Item: 'a,
{
fn new(iters: Rc<RefCell<Vec<I>>>) -> Self {
Self {
index: 0,
empty: false,
iters,
phantom: PhantomData,
}
}
}
impl<'a, I> Iterator for Row<'a, I>
where
I: Iterator,
I::Item: 'a,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
let mut iters = self.iters.borrow_mut();
if self.index == iters.len() {
return None;
}
let item = iters[self.index].next();
self.index += 1;
self.empty = item.is_none();
item
}
}
Things I've tried so far:
-
streaming_iterator
: Must beOption<&Self::Item>
, but the inner iterator needs to be&mut
-
itertools::IntoChunks
: I'd like to be able to pass iterator created bytranspose
around, composing it with more transposing iterators, but I had difficulty storing/composingIntoChunks
since it is consumed when you callinto_iter
.