use std::fs::File; use std::io; use std::io::BufRead; use std::collections::HashMap; /** Represents a CSV file **/ pub struct CsvFile { path : String, delim : String, pub header : Vec, pub content : Vec>, has_header : bool } /* * Iterator for the CSV file */ pub struct CsvFileIterator<'a> { file : &'a CsvFile, line : usize, column : usize, max_column : usize } impl <'a> Iterator for CsvFileIterator<'a> { type Item = HashMap<&'a String,&'a String>; fn next(&mut self) -> Option { let k = self.file.content.get(self.line)?; let it : HashMap<&'a String, &'a String> = self.file.header.iter().zip(k.iter()).collect(); self.line = self.line + 1; Some(it) } } impl CsvFile { pub fn new(path: &str, delim: &str, header: bool) -> CsvFile { CsvFile { path : String::from(path), delim: String::from(delim), header : Vec::new(), content : Vec::new(), has_header : header } } // TODO nicht gleich viele spalten fn parse_line(line : String, delim: &str) -> Vec { let mut columns : Vec = Vec::new(); for column in line.split(delim).collect::>() { columns.push(column.trim_matches(|c| c == '\'' || c == '\"').to_string()); } columns } pub fn from_file(path: &str, delim: &str, header: bool) -> Result { let fd = File::open(path)?; let reader = io::BufReader::new(fd); let mut column_names : Vec = Vec::new(); let mut lines : Vec> = Vec::new(); let mut first = true; for line in reader.lines() { let line = line?; if header && first { column_names.append(&mut CsvFile::parse_line(line, delim)); first = false; } else { lines.push(CsvFile::parse_line(line, delim)); } } Ok(CsvFile { path: String::from(path), delim : String::from(delim), header : column_names, content : lines, has_header: header } ) } pub fn iter(&self) -> CsvFileIterator { CsvFileIterator { file : self, line : 0, column : 0, max_column : self.header.len() } } }