1#[macro_use]
2#[allow(unused_imports)]
3extern crate easy_csv_derive;
4extern crate csv;
5
6#[derive(Debug)]
7pub enum Error {
8 CSVError(csv::Error),
9 MissingColumnError(String),
10 ParseError(String)
11}
12
13impl std::convert::From<csv::Error> for Error {
14 fn from(e: csv::Error) -> Error {
15 Error::CSVError(e)
16 }
17}
18
19pub trait CSVParsable<T> {
20 fn parse_header<R: std::io::Read>(
21 reader: &mut csv::Reader<R>) -> Result<Vec<usize>, ::Error>;
22 fn parse_row<R: std::io::Read>(
23 reader: &mut std::iter::Enumerate<csv::StringRecords<R>>,
24 col_indices: &Vec<usize>) -> Option<Result<T, ::Error>>;
25}
26
27pub struct CSVIterator<'a, T, R> where T: CSVParsable<T>, R: 'a, R: std::io::Read {
28 records: std::iter::Enumerate<csv::StringRecords<'a, R>>,
29 col_indices: Vec<usize>,
30 _marker: std::marker::PhantomData<T>
31}
32
33impl<'a, T, R> CSVIterator<'a, T, R> where T: CSVParsable<T>, R: 'a, R: std::io::Read {
34 pub fn new(mut reader: &'a mut csv::Reader<R>) -> Result<Self, ::Error> {
35 let col_indices = try!(T::parse_header(&mut reader));
36 Ok(CSVIterator {
37 records: reader.records::<'a>().into_iter().enumerate(),
38 col_indices: col_indices,
39 _marker: std::marker::PhantomData::<T> {}
40 })
41 }
42}
43
44impl<'a, T, R> Iterator for CSVIterator<'a, T, R> where T: CSVParsable<T>, R: std::io::Read {
45 type Item=Result<T, ::Error>;
46
47 fn next(&mut self) -> Option<Self::Item> {
48 T::parse_row(&mut self.records, &self.col_indices)
49 }
50}