I'm trying to create an Iterator interface using the csv
crate such that I can return a HashMap of col-name: value
and am running into a lifetime error I cannot figure out.
For the code below:
use csv::{
Reader,
StringRecord,
StringRecordsIter,
};
use std::collections::HashMap;
use std::fs::File;
pub struct Handler {
pub reader: Reader<File>
}
impl Handler {
pub fn new(file: File) -> Handler {
Handler { reader: Reader::from_reader(file) }
}
}
// type Row = HashMap<String, String>;
pub struct Row<'r> {
number: usize,
fields: HashMap<&'r str, &'r str>,
}
pub struct CSVIterator<'f> {
current_row: usize,
headers: StringRecord,
records: StringRecordsIter<'f, File>,
}
impl<'f> CSVIterator<'f> {
pub fn new(handler: &'f mut Handler) -> CSVIterator<'f> {
CSVIterator {
current_row: 0,
headers: handler.reader.headers().unwrap().clone(),
records: handler.reader.records(),
}
}
}
impl<'f> Iterator for CSVIterator<'f> {
type Item = Row<'f>;
fn next(&mut self) -> Option<Self::Item> {
let next_record = self.records.next();
if next_record.is_none() {
return None;
}
let record = next_record.unwrap().unwrap();
let fields = make_fields(&record, &self.headers);
let row = Row {
number: self.current_row,
fields: fields,
};
return Some(row)
}
}
fn make_fields<'r>(
record: &'r StringRecord, header: &'r StringRecord
) -> HashMap<&'r str, &'r str> {
let mut row: HashMap<&str, &str> = HashMap::new();
for (colname, value) in header.iter().zip(record) {
row.insert(colname, value);
}
row
}
I'm getting the following error:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/csvio.rs:55:43
|
55 | let fields = make_fields(&record, &self.headers);
| ^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/csvio.rs:47:13
|
47 | fn next(&mut self) -> Option<Self::Item> {
| ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/csvio.rs:55:43
|
55 | let fields = make_fields(&record, &self.headers);
| ^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'f` as defined here...
--> src/csvio.rs:44:6
|
44 | impl<'f> Iterator for CSVIterator<'f> {
| ^^
note: ...so that the types are compatible
--> src/csvio.rs:47:46
|
47 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
48 | | let next_record = self.records.next();
49 | |
50 | | if next_record.is_none() {
... |
61 | | return Some(row)
62 | | }
| |_____^
= note: expected `<CSVIterator<'f> as Iterator>`
found `<CSVIterator<'_> as Iterator>`
For more information about this error, try `rustc --explain E0495`.
I may not intuitively understand the lifetime requirements for the next
method here, can someone point me in the right direction?
Thanks!