1 //! CSV impl and reexported types
2 
3 extern crate csv;
4 
5 pub use self::csv::{Reader, Writer, Result, ReaderBuilder};
6 use std::path::Path;
7 use std::io::{Read, Write};
8 
9 impl<'a> super::TableSlice<'a> {
10     /// Write the table to the specified writer.
to_csv<W: Write>(&self, w: W) -> Result<Writer<W>>11     pub fn to_csv<W: Write>(&self, w: W) -> Result<Writer<W>> {
12         self.to_csv_writer(Writer::from_writer(w))
13     }
14 
15     /// Write the table to the specified writer.
16     ///
17     /// This allows for format customisation.
to_csv_writer<W: Write>(&self, mut writer: Writer<W>) -> Result<Writer<W>>18     pub fn to_csv_writer<W: Write>(&self,
19                                 mut writer: Writer<W>)
20                                 -> Result<Writer<W>> {
21         for title in self.titles {
22             writer.write_record(title.iter().map(|c| c.get_content()))?;
23         }
24         for row in self.rows {
25             writer.write_record(row.iter().map(|c| c.get_content()))?;
26         }
27 
28         writer.flush()?;
29         Ok(writer)
30     }
31 }
32 
33 impl super::Table {
34     /// Create a table from a CSV string
35     ///
36     /// For more customisability use `from_csv()`
from_csv_string(csv_s: &str) -> Result<Self>37     pub fn from_csv_string(csv_s: &str) -> Result<Self> {
38         Ok(Self::from_csv(
39             &mut ReaderBuilder::new()
40                 .has_headers(false)
41                 .from_reader(csv_s.as_bytes())))
42     }
43 
44     /// Create a table from a CSV file
45     ///
46     /// For more customisability use `from_csv()`
from_csv_file<P: AsRef<Path>>(csv_p: P) -> Result<Self>47     pub fn from_csv_file<P: AsRef<Path>>(csv_p: P) -> Result<Self> {
48         Ok(Self::from_csv(
49             &mut ReaderBuilder::new()
50                 .has_headers(false)
51                 .from_path(csv_p)?))
52     }
53 
54     /// Create a table from a CSV reader
from_csv<R: Read>(reader: &mut Reader<R>) -> Self55     pub fn from_csv<R: Read>(reader: &mut Reader<R>) -> Self {
56         Self::init(reader
57                         .records()
58                         .map(|row| {
59                                 super::Row::new(row.unwrap()
60                                             .into_iter()
61                                             .map(|cell| super::Cell::new(&cell))
62                                             .collect())
63                             })
64                         .collect())
65     }
66 
67 
68     /// Write the table to the specified writer.
to_csv<W: Write>(&self, w: W) -> Result<Writer<W>>69     pub fn to_csv<W: Write>(&self, w: W) -> Result<Writer<W>> {
70         self.as_ref().to_csv(w)
71     }
72 
73     /// Write the table to the specified writer.
74     ///
75     /// This allows for format customisation.
to_csv_writer<W: Write>(&self, writer: Writer<W>) -> Result<Writer<W>>76     pub fn to_csv_writer<W: Write>(&self, writer: Writer<W>) -> Result<Writer<W>> {
77         self.as_ref().to_csv_writer(writer)
78     }
79 }
80 
81 
82 #[cfg(test)]
83 mod tests {
84     use {Table, Row, Cell};
85 
86     static CSV_S: &'static str = "ABC,DEFG,HIJKLMN\n\
87                                 foobar,bar,foo\n\
88                                 foobar2,bar2,foo2\n";
89 
test_table() -> Table90     fn test_table() -> Table {
91         let mut table = Table::new();
92         table
93             .add_row(Row::new(vec![Cell::new("ABC"), Cell::new("DEFG"), Cell::new("HIJKLMN")]));
94         table.add_row(Row::new(vec![Cell::new("foobar"), Cell::new("bar"), Cell::new("foo")]));
95         table.add_row(Row::new(vec![Cell::new("foobar2"),
96                                     Cell::new("bar2"),
97                                     Cell::new("foo2")]));
98         table
99     }
100 
101     #[test]
from()102     fn from() {
103         assert_eq!(test_table().to_string().replace("\r\n", "\n"),
104                     Table::from_csv_string(CSV_S)
105                         .unwrap()
106                         .to_string()
107                         .replace("\r\n", "\n"));
108     }
109 
110     #[test]
to()111     fn to() {
112         assert_eq!(
113             String::from_utf8(
114                 test_table()
115                     .to_csv(Vec::new())
116                     .unwrap()
117                     .into_inner()
118                     .unwrap()
119                 ).unwrap(),
120                 CSV_S);
121     }
122 
123     #[test]
trans()124     fn trans() {
125         assert_eq!(
126             Table::from_csv_string(
127                 &String::from_utf8(
128                     test_table()
129                         .to_csv(Vec::new())
130                         .unwrap()
131                         .into_inner()
132                         .unwrap()
133                 ).unwrap()
134             ).unwrap()
135             .to_string()
136             .replace("\r\n", "\n"),
137             test_table().to_string().replace("\r\n", "\n"));
138     }
139 
140     #[test]
extend_table()141     fn extend_table() {
142         let mut table = Table::new();
143         table.add_row(Row::new(vec![Cell::new("ABC"), Cell::new("DEFG"), Cell::new("HIJKLMN")]));
144         table.extend(vec![vec!["A", "B", "C"]]);
145         let t2 = table.clone();
146         table.extend(t2.rows);
147         assert_eq!(table.get_row(1).unwrap().get_cell(2).unwrap().get_content(), "C");
148         assert_eq!(table.get_row(2).unwrap().get_cell(1).unwrap().get_content(), "DEFG");
149     }
150 }