1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use std::io::{Result, Write};
use termcolor::{BufferWriter, ColorChoice, WriteColor};
use crate::Row;
pub struct Table {
rows: Vec<Row>,
widths: Vec<usize>,
}
impl Table {
pub fn new(rows: Vec<Row>) -> Table {
validate_equal_columns(&rows);
let widths = get_widths(&rows);
Table { rows, widths }
}
pub fn print_std(&self) -> Result<()> {
let writer = BufferWriter::stdout(ColorChoice::Always);
print_horizontal_separator(&writer, &self.widths)?;
for row in self.rows.iter() {
let buffers = row.buffers(&writer, &self.widths)?;
for line in buffers.into_iter() {
print_str(&writer, "|")?;
for buffer in line.into_iter() {
print_str(&writer, " ")?;
writer.print(&buffer)?;
print_str(&writer, " |")?;
}
println_str(&writer, "")?;
}
print_horizontal_separator(&writer, &self.widths)?;
}
Ok(())
}
}
fn print_str(writer: &BufferWriter, s: &str) -> Result<()> {
let mut buffer = writer.buffer();
buffer.reset()?;
write!(&mut buffer, "{}", s)?;
writer.print(&buffer)?;
Ok(())
}
fn println_str(writer: &BufferWriter, s: &str) -> Result<()> {
let mut buffer = writer.buffer();
buffer.reset()?;
writeln!(&mut buffer, "{}", s)?;
writer.print(&buffer)?;
Ok(())
}
fn print_horizontal_separator(writer: &BufferWriter, widths: &[usize]) -> Result<()> {
print_str(writer, "+")?;
for width in widths.iter() {
let s = std::iter::repeat('-').take(width + 2).collect::<String>();
print_str(writer, &s)?;
print_str(writer, "+")?;
}
println_str(writer, "")?;
Ok(())
}
fn validate_equal_columns(rows: &[Row]) {
if rows.len() <= 1 {
return;
}
let columns = rows[0].columns();
for row in rows.iter().skip(1) {
if columns != row.columns() {
panic!("Mismatch column numbers in different rows");
}
}
}
fn get_widths(rows: &[Row]) -> Vec<usize> {
if rows.is_empty() {
return Vec::new();
}
let mut widths = rows[0].widths();
for row in rows.iter().skip(1) {
let new_widths = row.widths();
for (width, new_width) in widths.iter_mut().zip(new_widths.into_iter()) {
*width = std::cmp::max(new_width, *width);
}
}
widths
}