1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/// contains Row iterator for the csv data
use crate::{
    ast::{ddl::ColumnDef, Value},
    data_value::cast_data_value,
    DataValue,
};
use csv::{ReaderBuilder, StringRecordsIntoIter};
use std::io::{BufReader, Read};

pub struct CsvRows<R>
where
    R: Read + Send + Sync,
{
    into_iter: StringRecordsIntoIter<BufReader<R>>,
    column_defs: Vec<ColumnDef>,
}

impl<R> CsvRows<R>
where
    R: Read + Send + Sync,
{
    pub fn new(input: BufReader<R>, column_defs: Vec<ColumnDef>) -> Self {
        let into_iter = ReaderBuilder::new()
            .has_headers(false)
            .from_reader(input)
            .into_records();

        CsvRows {
            into_iter,
            column_defs,
        }
    }
}

impl<R> Iterator for CsvRows<R>
where
    R: Read + Send + Sync,
{
    type Item = Vec<DataValue>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.into_iter.next() {
            Some(row) => match row {
                Ok(row) => {
                    let data_values: Vec<DataValue> = self
                        .column_defs
                        .iter()
                        .zip(row.iter())
                        .map(|(column_def, record)| {
                            cast_data_value(
                                &Value::String(record.to_string()),
                                &column_def.data_type_def.data_type,
                            )
                        })
                        .collect();
                    Some(data_values)
                }
                Err(_e) => None,
            },
            None => None,
        }
    }
}