I'm trying to create an iterator trait that provides a specific type of resource, so I can implement multiple source types. I'd like to create a source for reading from a CSV file, a binary etc..
I'm using the rust-csv
library for deserializing CSV data:
#[derive(RustcDecodable)]
struct BarRecord {
bar: u32
}
trait BarSource : Iterator {}
struct CSVBarSource {
records: csv::DecodedRecords<'static, std::fs::File, BarRecord>,
}
impl CSVBarSource {
pub fn new(path: String) -> Option<CSVBarSource> {
match csv::Reader::from_file(path) {
Ok(reader) => Some(CSVBarSource { records: reader.decode() }),
Err(_) => None
}
}
}
impl Iterator for CSVBarSource {
type Item = BarRecord;
fn next(&mut self) -> Option<BarRecord> {
match self.records.next() {
Some(Ok(e)) => Some(e),
_ => None
}
}
}
I cannot seem to store a reference to the DecodedRecords
iterator returned by the CSV reader due to lifetime issues:
error: reader does not live long enough
How can I store a reference to the decoded records iterator and what am I doing wrong?
According to the documentation,
Reader::decode
is defined as:That is
reader.decode()
cannot outlivereader
(because of'a
). And with this declaration:reader
would need a'static
lifetime, that is it would need to live forever, which it does not hence the error you get “reader
does not live long enough”.You should store
reader
directly inCSVBarSource
:And call
decode
only as needed.