use csv;
use std::io::{self, Write};
use crate::{Cursor};
#[derive(Debug)]
pub struct Table {
data: Vec<Vec<String>>,
}
impl Table {
pub fn new() -> Self {
Self {
data: vec![vec![String::new()]],
}
}
pub fn from_path(path: &str) -> Self {
let mut rdr = csv::Reader::from_path(path).unwrap();
let mut data: Vec<Vec<String>> = Vec::new();
let headers: Vec<String> = rdr
.headers()
.unwrap()
.into_iter()
.map(|x| x.to_string())
.collect();
data.push(headers);
for record in rdr.into_records() {
let strs = record
.unwrap()
.into_iter()
.map(|x| x.to_owned())
.collect();
data.push(strs);
}
Table { data }
}
pub fn dims(&self) -> (usize, usize) {
let dimy = self.data.len();
let dimx = self.data[0].len();
(dimx, dimy)
}
pub fn col_widths(&self) -> Vec<i32> {
self.data.iter().fold(
self.data[0].iter().map(|h| h.len()).map(|x| x as i32).collect::<Vec<i32>>(),
|maxes, cur| {
maxes
.iter()
.zip(cur.iter())
.map(|(m, c)| std::cmp::max::<i32>(*m, c.len() as i32))
.collect::<Vec<i32>>()
},
)
}
pub fn fmt_iter(&self) -> Vec<Vec<String>>{
let widths = self.col_widths();
self.data.iter().map(|row|
row.iter().zip(widths.iter()).map(|(cell, width)| {
let mut p = cell.clone();
for _ in cell.len()..(*width as usize) {
p.push(' ');
}
p
}).collect()
).collect()
}
pub fn rows(&self) -> Vec<Vec<String>> {
self.data.clone()
}
pub fn get(&self, c: Cursor) -> String {
self.data[c.y][c.x].clone()
}
pub fn update(&mut self, c: Cursor, new: String) {
self.data[c.y][c.x] = new;
}
pub fn add_row_before(&mut self, c: Cursor) {
self.add_row(c.y);
}
pub fn add_row_after(&mut self, c: Cursor) {
self.add_row(c.y + 1);
}
fn add_row(&mut self, r: usize) {
let (w, _) = self.dims();
let new_row = vec![String::new(); w];
self.data.insert(r, new_row);
}
pub fn add_col_before(&mut self, c: Cursor) {
self.add_col(c.x);
}
pub fn add_col_after(&mut self, c: Cursor) {
self.add_col(c.x + 1);
}
fn add_col(&mut self, c: usize) {
for row in &mut self.data {
row.insert(c, String::new());
}
}
pub fn clear(&mut self, c: Cursor) {
self.update(c, String::new());
}
pub fn delete_row(&mut self, c: &mut Cursor) {
self.data.remove(c.y);
}
pub fn delete_col(&mut self, c: &mut Cursor) {
for row in &mut self.data {
row.remove(c.x);
}
}
pub fn save_to_path(&self, path: String) {
let mut wtr = csv::Writer::from_path(path).unwrap();
for row in self.data.clone().into_iter() {
wtr.write_record(row).unwrap();
}
wtr.flush().unwrap();
}
}