1use std::{fmt::Display, io::Write};
9
10use crate::{
11 file::csv::{RowData, WriteRow},
12 table::cell::{Align, Cell, Style},
13};
14
15#[derive(Default)]
16pub struct Row {
17 cells: Vec<Cell>,
18 max_len: usize,
19}
20
21#[derive(PartialEq)]
22pub enum ColumnJoinType {
23 Normal,
24 Spaced,
25 Plus,
26}
27
28impl Row {
29 #[inline]
44 #[must_use]
45 pub fn is_empty(&self) -> bool {
46 self.cells.is_empty()
47 }
48
49 #[inline]
61 #[must_use]
62 pub fn len(&self) -> usize {
63 self.cells.len()
64 }
65
66 #[inline]
76 #[must_use]
77 pub fn push<T>(mut self, value: T, align: Align, style: Style) -> Self
78 where
79 T: Display,
80 {
81 let value = value.to_string();
82 let len = value.len();
83 let cell = Cell::new(value, align, style);
84
85 if len > self.max_len {
86 self.max_len = len;
87 }
88
89 self.cells.push(cell);
90 self
91 }
92
93 #[inline]
103 #[must_use]
104 pub fn blank(self) -> Self {
105 self.push("", Align::Left, Style::Normal)
106 }
107
108 #[inline]
110 #[must_use]
111 pub fn size(&self) -> usize {
112 self.to_string(None, ColumnJoinType::Spaced).len()
113 }
114
115 #[inline]
121 #[must_use]
122 pub fn get_column_size(&self, index: usize) -> usize {
123 assert!(index < self.cells.len(), "Invalid column index.");
124 self.cells[index].size()
125 }
126
127 #[inline]
129 pub fn print(&self, stdout: &mut impl Write, sizes: &Vec<usize>, join_type: ColumnJoinType) {
130 writeln!(stdout, "{}", self.to_string(Some(sizes), join_type)).unwrap();
131 }
132
133 #[must_use]
135 fn to_string(&self, sizes: Option<&Vec<usize>>, join_type: ColumnJoinType) -> String {
136 let join_str = match join_type {
137 ColumnJoinType::Normal => "|",
138 ColumnJoinType::Spaced => " | ",
139 ColumnJoinType::Plus => "+",
140 };
141
142 let line = self
143 .cells
144 .iter()
145 .enumerate()
146 .map(|(index, cell)| {
147 let size = match sizes {
148 Some(sizes) => sizes[index],
149 None => cell.size(),
150 };
151
152 cell.to_sized_string(size)
153 })
154 .collect::<Vec<String>>()
155 .join(join_str);
156
157 if join_type == ColumnJoinType::Spaced {
158 format!("| {line} |")
159 } else {
160 format!("|{line}|")
161 }
162 }
163}
164
165impl WriteRow for Row {
166 fn as_row(&self, row_data: &mut RowData) {
167 for cell in &self.cells {
168 row_data.push(cell.value());
169 }
170 }
171}