Implementing Iterator for a type containing a vector


#1

I have a type (let’s call it Reader for now) which I would like to have two main methods:

  1. Read a bulk set of some data from a source that does not stream easily, and
  2. Stream data read from some source out into a consumer.

The former method is straightforward, and for the latter I would ideally like to use an iterator, as they seem to encompass exactly what I want.

At present, my implementation (details aside) looks a little like this:

pub struct Reader<T>{ 
    buffer: Vec<T>
}

impl<T> Reader<T> {
    pub fn read_in<S>(source: S) -> Reader<T> { 
        // Read some data from t, into a buffer
        let buffer : Vec<T> = Vec::new();
        //...
        Reader { buffer: buffer }
    }
}

impl<T> Iterator for Reader<T> {
    type Item = T;
    
    // Note, that next returns T, not &T
    fn next(self: &mut Reader<T>) -> Option<T> {
        unimplemented!()
        // Possible option?
        // buffer.into_iter().next()
    }
}

I am, unfortunately, at a loss as to how to cleanly implement next (or another method). I obviously cannot have a reference to the Vec iterator in the type, as the borrow checker disallows it, and storing an explicit index in the type would invalidate the point of having an iterator for Vec at all.

One option, of course, would be to mandate that users simply use the into_iter method of the inner buffer, but I plan on having a family of Readers, each with a different underlying storage, and a unifed iterator interface.

Any advice would be very welcome!


#2

if you use a VecDeque you could use it’s pop_front method to implament the Iterator

playgound


#3

Alternatively, store the vectors iterator instead of the actual vector

pub struct Reader<T>{ 
    buffer: vec::IntoIter<T>
}

impl<T> Reader<T> {
    pub fn read_in<S>(source: S) -> Reader<T> { 
        // Read some data from t, into a buffer
        let buffer : Vec<T> = Vec::new();
        //...
        Reader { buffer: buffer.into_iter() }
    }
}


#4

That looks like it’s probably the best solution for me - I should just be able to drop it into the type in place of a vector. Thanks!


#5

That also looks like a great solution, thanks! In fact, I might try this one, as it should let me implement the iterator methods with even less effort…