0

Newbie question: how do I store an iterator in a struct, and half-way the struct's lifetime, replace that iterator with a new one? My test program, takes a vec of strings, and wraps that in a CharStream (or CharIterator or CharGenerator - whatever you want to call it). Goal is to do this without transforming or copying the original data, so no concat or map() or collect() into an intermediate list of some sorts.

use core::str::Chars;

struct CharStream<'a> {
    stream: std::vec::Vec<String>, //test data
    line: usize, //test data
    char_it: Chars<'a>
}

impl<'a> CharStream<'a> {
    fn new(stream: std::vec::Vec<String>) -> CharStream<'a> {
        CharStream { stream: stream, line: 0, char_it: stream[0].chars()}
    }

    /// next() should give the next char in the 'stream'.
    /// to keep the function simple, it just returns the first char of each line...
    /// and tries to replace the chars iterator with the next one.
    fn next(&mut self) -> Option<char> {
        self.line += 1;
        self.char_it = self.stream[self.line].chars(); //<< this fails!
        self.char_it.next()
    }
}

fn main() {
    //just test data, imagine some stream, read line by line:
    let mut stream = Vec::new();
    stream.push("initial".to_string());
    stream.push("second".to_string());
    stream.push("third".to_string());

    let mut cont = CharStream::new(stream);

    for i in 0..1 {
        let c = cont.next();
        println!("{:?}", c);
    }
}

If possible, I'm looking for the smallest fix to this code, but if in Rust, another pattern is better to implement this... The goal remains to be able to generate one stream from another without intermediate storage or full consumption of the incoming stream.

Erik Bongers
  • 416
  • 2
  • 10
  • This is *almost* a perfect duplicate of [Is there an owned version of String::chars?](https://stackoverflow.com/questions/47193584/is-there-an-owned-version-of-stringchars) The only thing you need to add is `Flatten`ing the `Vec`. – trent May 31 '20 at 22:15
  • @Stargateur, stackoverflow suggested that post, but I'm afraid I don't get how to fix my problem. – Erik Bongers May 31 '20 at 23:07
  • @trentcl: that "almost duplicate" is indeed related. But, even in that post it says "Downside is additional allocation and a space overhead", so there seems to be a copy of data involved, while I'm looking for a (excuse my french) a pointer-only solution. – Erik Bongers May 31 '20 at 23:11
  • However, the `flatten` thing is closer to what I'm looking for and would likely work for a vec as a source. (I'm still suspicious that it might copy data, though) – Erik Bongers May 31 '20 at 23:18
  • 1
    @Erik Read the other answers. They aren't all using `Vec`. – trent May 31 '20 at 23:20
  • @ErikBongers are you sure this is creating intermediate storage? Could you compile the working version in https://play.rust-lang.org/, using the `Release` mode and instead of running it, choosing to generate the `LLVM IR`? I'd bet these copies get optimized away by the compiler when you're in release mode. If that's not the case, then... I'm not sure how to proceed. – felix91gr Jun 01 '20 at 00:05

0 Answers0