text_grid/
grid.rs

1use std::borrow::Borrow;
2use std::fmt::{Debug, Display, Formatter};
3
4use crate::cells_csv_writer::write_csv;
5use crate::{grid_builder::*, Cells, CellsSchema, CellsSchemaExt, DefaultCellsSchema};
6/// Generate a table using the columns defined by [`Cells`](crate::Cells).
7///
8/// # Examples
9///
10/// ```
11/// use text_grid::*;
12/// struct RowData {
13///     a: u32,
14///     b: u32,
15/// }
16/// impl Cells for RowData {
17///     fn fmt(f: &mut CellsFormatter<Self>) {
18///         f.column("a", |s| s.a);
19///         f.column("b", |s| s.b);
20///     }
21/// }
22///
23/// let rows = [
24///     RowData { a: 300, b: 1 },
25///     RowData { a: 2, b: 200 },
26/// ];
27/// let g = to_grid(rows);
28/// assert_eq!(format!("\n{g}"), r#"
29///   a  |  b  |
30/// -----|-----|
31///  300 |   1 |
32///    2 | 200 |
33/// "#);
34/// ```
35pub fn to_grid(rows: impl IntoIterator<Item = impl Cells>) -> String {
36    to_grid_with_schema(rows, DefaultCellsSchema::default())
37}
38
39/// Generate a table using the columns defined by [`CellsSchema`](crate::CellsSchema).
40pub fn to_grid_with_schema<T>(
41    rows: impl IntoIterator<Item = impl Borrow<T>>,
42    schema: impl CellsSchema<Source = T>,
43) -> String {
44    GridBuilder::from_iter_with_schema(rows, schema).to_string()
45}
46
47/// Generate csv using the columns defined by [`Cells`](crate::Cells).
48pub fn to_csv(rows: impl IntoIterator<Item = impl Cells>) -> String {
49    to_csv_with_schema(rows, DefaultCellsSchema::default())
50}
51
52/// Generate csv using the columns defined by [`CellsSchema`](crate::CellsSchema).
53pub fn to_csv_with_schema<T>(
54    rows: impl IntoIterator<Item = impl Borrow<T>>,
55    schema: impl CellsSchema<Source = T>,
56) -> String {
57    let mut bytes = Vec::new();
58    {
59        let mut csv_writer = csv::Writer::from_writer(&mut bytes);
60        write_csv(&mut csv_writer, rows, schema, ".").unwrap();
61        csv_writer.flush().unwrap();
62    }
63    String::from_utf8(bytes).unwrap()
64}
65
66/// A builder used to create plain-text table.
67///
68/// This type will be removed in the future. Use the following methods instead.
69///
70/// - [`to_grid`](crate::to_grid)
71/// - [`to_grid_with_schema`](crate::to_grid_with_schema)
72/// - [`to_csv`](crate::to_csv)
73/// - [`to_csv_with_schema`](crate::to_csv_with_schema)
74#[deprecated = "use `to_grid`"]
75pub struct Grid<T, S = DefaultCellsSchema<T>> {
76    source: Vec<T>,
77    schema: S,
78}
79
80#[allow(deprecated)]
81impl<T: Cells> Default for Grid<T, DefaultCellsSchema<T>> {
82    fn default() -> Self {
83        Self::new()
84    }
85}
86
87#[allow(deprecated)]
88impl<T: Cells> Grid<T, DefaultCellsSchema<T>> {
89    /// Create a new `Grid` with [`DefaultCellsSchema`] and prepare header rows.
90    pub fn new() -> Self {
91        Self::with_schema(DefaultCellsSchema::default())
92    }
93}
94
95#[allow(deprecated)]
96impl<T, S: CellsSchema<Source = T>> Grid<T, S> {
97    /// Create a new `Grid` with specified schema and prepare header rows.
98    pub fn with_schema(schema: S) -> Self {
99        Grid {
100            source: Vec::new(),
101            schema,
102        }
103    }
104
105    pub fn from_iter_with_schema(iter: impl IntoIterator<Item = T>, schema: S) -> Self {
106        let mut g = Self::with_schema(schema);
107        g.extend(iter);
108        g
109    }
110
111    /// Append a row to the bottom of the grid.
112    pub fn push(&mut self, item: T) {
113        self.source.push(item);
114    }
115
116    pub fn to_csv(&self) -> String {
117        let mut bytes = Vec::new();
118        {
119            let mut csv_writer = csv::Writer::from_writer(&mut bytes);
120            write_csv(&mut csv_writer, &self.source, &self.schema.as_ref(), ".").unwrap();
121            csv_writer.flush().unwrap();
122        }
123        String::from_utf8(bytes).unwrap()
124    }
125
126    fn build(&self) -> GridBuilder {
127        GridBuilder::from_iter_with_schema(&self.source, &self.schema.as_ref())
128    }
129}
130
131#[allow(deprecated)]
132impl<T, S: CellsSchema<Source = T>> Extend<T> for Grid<T, S> {
133    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
134        self.source.extend(iter);
135    }
136}
137
138#[allow(deprecated)]
139impl<T: Cells> FromIterator<T> for Grid<T> {
140    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
141        let mut g = Self::new();
142        g.extend(iter);
143        g
144    }
145}
146
147#[allow(deprecated)]
148impl<T, S: CellsSchema<Source = T>> Display for Grid<T, S> {
149    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
150        Display::fmt(&self.build(), f)
151    }
152}
153
154#[allow(deprecated)]
155impl<T, S: CellsSchema<Source = T>> Debug for Grid<T, S> {
156    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
157        Debug::fmt(&self.build(), f)
158    }
159}