<commit_before>use csv::{Reader, ReaderBuilder};
use std::io;

pub struct CsvReader<T> {
  reader: Reader<T>,
  headers: bool,
}

impl<T: io::Read> CsvReader<T> {
  pub fn new(reader: T, delimiter: u8, headers: bool) -> CsvReader<T> {
    let reader = ReaderBuilder::new()
      .delimiter(delimiter)
      .has_headers(false)
      .from_reader(reader);

    CsvReader { reader, headers }
  }
}

impl<T: io::Read> crate::Read for CsvReader<T> {
  fn read(&mut self) -> Result<crate::Table, crate::Error> {
    let mut table = crate::Table::with_headers(self.headers);

    for result in self.reader.records() {
      match result {
        Ok(record) => {
          let row: Vec<String> = record.iter().map(|field| String::from(field)).collect();
          table.push_row(row);
        }
        Err(_) => {
          return Err(crate::Error {
            kind: crate::ErrorKind::Read,
          });
        }
      }
    }

    Ok(table)
  }
}

mod tests {
  use super::*;
  use crate::Read;

  #[test]
  fn read() {
    let test_cases = vec![
      (
        "alice\t80",
        false,
        crate::Table::from(vec![vec![String::from("alice"), String::from("80")]], false),
      ),
      (
        "alice\t80\nbob\t100",
        false,
        crate::Table::from(
          vec![<commit_msg>Suppress false positive warnings<commit_after>use csv::{Reader, ReaderBuilder};
use std::io;

pub struct CsvReader<T> {
  reader: Reader<T>,
  headers: bool,
}

impl<T: io::Read> CsvReader<T> {
  pub fn new(reader: T, delimiter: u8, headers: bool) -> CsvReader<T> {
    let reader = ReaderBuilder::new()
      .delimiter(delimiter)
      .has_headers(false)
      .from_reader(reader);

    CsvReader { reader, headers }
  }
}

impl<T: io::Read> crate::Read for CsvReader<T> {
  fn read(&mut self) -> Result<crate::Table, crate::Error> {
    let mut table = crate::Table::with_headers(self.headers);

    for result in self.reader.records() {
      match result {
        Ok(record) => {
          let row: Vec<String> = record.iter().map(|field| String::from(field)).collect();
          table.push_row(row);
        }
        Err(_) => {
          return Err(crate::Error {
            kind: crate::ErrorKind::Read,
          });
        }
      }
    }

    Ok(table)
  }
}

mod tests {
  #[allow(unused)]
  use super::*;
  #[allow(unused)]
  use crate::Read;

  #[test]
  fn read() {
    let test_cases = vec![
      (
        "alice\t80",
        false,
        crate::Table::from(vec![vec![String::from("alice"), String::from("80")]], false),
      ),
      (
        "alice\t80\nbob\t100",
        false,
        crate::Table::from(
          vec![
{'fraction_non_alphanumeric': 0.1711270260082925, 'fraction_numerical': 0.007538635506973238, 'mean_word_length': 2.420103092783505, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5415707', 'n_tokens_mistral': 920, 'n_tokens_neox': 910, 'n_words': 178}