1use std::io::{Error, Write};
3use std::iter::FromIterator;
4use std::slice::{Iter, IterMut};
5use std::ops::{Index, IndexMut};
7
8use super::Terminal;
9
10use super::format::{ColumnPosition, TableFormat};
11use super::utils::NEWLINE;
12use super::Cell;
13
14#[derive(Clone, Debug, Hash, PartialEq, Eq)]
16pub struct Row {
17 cells: Vec<Cell>,
18}
19
20impl Row {
21 pub fn new(cells: Vec<Cell>) -> Row {
23 Row { cells }
24 }
25
26 pub fn empty() -> Row {
28 Self::new(vec![Cell::default(); 0])
29 }
30
31 pub(crate) fn column_count(&self) -> usize {
36 self.cells.iter().map(|c| c.get_hspan()).sum()
37 }
38
39 pub fn len(&self) -> usize {
41 self.cells.len()
42 }
44
45 pub fn is_empty(&self) -> bool {
47 self.cells.is_empty()
48 }
49
50 fn get_height(&self) -> usize {
53 let mut height = 1; for cell in &self.cells {
55 let h = cell.get_height();
56 if h > height {
57 height = h;
58 }
59 }
60 height
61 }
62
63 pub(crate) fn get_column_width(&self, column: usize, format: &TableFormat) -> usize {
67 let mut i = 0;
68 for c in &self.cells {
69 if i + c.get_hspan() > column {
70 if c.get_hspan() == 1 {
71 return c.get_width();
72 }
73 let (lp, rp) = format.get_padding();
74 let sep = format
75 .get_column_separator(ColumnPosition::Intern)
76 .map(|_| 1)
77 .unwrap_or_default();
78 let rem = lp + rp + sep;
79 let mut w = c.get_width();
80 if w > rem {
81 w -= rem;
82 } else {
83 w = 0;
84 }
85 return (w as f64 / c.get_hspan() as f64).ceil() as usize;
86 }
87 i += c.get_hspan();
88 }
89 0
90 }
91
92 pub fn get_cell(&self, idx: usize) -> Option<&Cell> {
94 self.cells.get(idx)
95 }
96
97 pub fn get_mut_cell(&mut self, idx: usize) -> Option<&mut Cell> {
99 self.cells.get_mut(idx)
100 }
101
102 pub fn set_cell(&mut self, cell: Cell, idx: usize) -> Result<(), &str> {
104 if idx >= self.len() {
105 return Err("Cannot find cell");
106 }
107 self.cells[idx] = cell;
108 Ok(())
109 }
110
111 pub fn add_cell(&mut self, cell: Cell) {
113 self.cells.push(cell);
114 }
115
116 pub fn insert_cell(&mut self, index: usize, cell: Cell) {
119 if index < self.cells.len() {
120 self.cells.insert(index, cell);
121 } else {
122 self.add_cell(cell);
123 }
124 }
125
126 pub fn remove_cell(&mut self, index: usize) {
128 if index < self.cells.len() {
129 self.cells.remove(index);
130 }
131 }
132
133 pub fn iter(&self) -> Iter<Cell> {
135 self.cells.iter()
136 }
137
138 pub fn iter_mut(&mut self) -> IterMut<Cell> {
140 self.cells.iter_mut()
141 }
142
143 fn __print<T: Write + ?Sized, F>(
145 &self,
146 out: &mut T,
147 format: &TableFormat,
148 col_width: &[usize],
149 f: F,
150 ) -> Result<usize, Error>
151 where
152 F: Fn(&Cell, &mut T, usize, usize, bool) -> Result<(), Error>,
153 {
154 let height = self.get_height();
155 for i in 0..height {
156 out.write_all(&vec![b' '; format.get_indent()])?;
158 format.print_column_separator(out, ColumnPosition::Left)?;
159 let (lp, rp) = format.get_padding();
160 let mut j = 0;
161 let mut hspan = 0; while j + hspan < col_width.len() {
163 out.write_all(&vec![b' '; lp])?; let skip_r_fill = (j == col_width.len() - 1)
167 && format.get_column_separator(ColumnPosition::Right).is_none();
168 match self.get_cell(j) {
169 Some(c) => {
170 let mut w = col_width[j + hspan..j + hspan + c.get_hspan()].iter().sum();
172 let real_span = c.get_hspan() - 1;
173 w += real_span * (lp + rp)
174 + real_span
175 * format
176 .get_column_separator(ColumnPosition::Intern)
177 .map(|_| 1)
178 .unwrap_or_default();
179 f(c, out, i, w, skip_r_fill)?;
181 hspan += real_span; }
183 None => f(&Cell::default(), out, i, col_width[j + hspan], skip_r_fill)?,
184 };
185 out.write_all(&vec![b' '; rp])?; if j + hspan < col_width.len() - 1 {
187 format.print_column_separator(out, ColumnPosition::Intern)?;
188 }
189 j += 1;
190 }
191 format.print_column_separator(out, ColumnPosition::Right)?;
192 out.write_all(NEWLINE)?;
193 }
194 Ok(height)
195 }
196
197 pub(crate) fn print<T: Write + ?Sized>(
201 &self,
202 out: &mut T,
203 format: &TableFormat,
204 col_width: &[usize],
205 ) -> Result<usize, Error> {
206 self.__print(out, format, col_width, Cell::print)
207 }
208
209 pub(crate) fn print_term<T: Terminal + ?Sized>(
213 &self,
214 out: &mut T,
215 format: &TableFormat,
216 col_width: &[usize],
217 ) -> Result<usize, Error> {
218 self.__print(out, format, col_width, Cell::print_term)
219 }
220
221 pub fn print_html<T: Write + ?Sized>(&self, out: &mut T, col_num: usize) -> Result<(), Error> {
225 let mut printed_columns = 0;
226 for cell in self.iter() {
227 printed_columns += cell.print_html(out)?;
228 }
229 for _ in 0..col_num - printed_columns {
231 Cell::default().print_html(out)?;
232 }
233 Ok(())
234 }
235}
236
237impl Default for Row {
238 fn default() -> Row {
239 Row::empty()
240 }
241}
242
243impl Index<usize> for Row {
244 type Output = Cell;
245 fn index(&self, idx: usize) -> &Self::Output {
246 &self.cells[idx]
247 }
248}
249
250impl IndexMut<usize> for Row {
251 fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
252 &mut self.cells[idx]
253 }
254}
255
256impl<A: ToString> FromIterator<A> for Row {
257 fn from_iter<T>(iterator: T) -> Row
258 where
259 T: IntoIterator<Item = A>,
260 {
261 Self::new(iterator.into_iter().map(|ref e| Cell::from(e)).collect())
262 }
263}
264
265impl<T, A> From<T> for Row
266where
267 A: ToString,
268 T: IntoIterator<Item = A>,
269{
270 fn from(it: T) -> Row {
271 Self::from_iter(it)
272 }
273}
274
275impl<'a> IntoIterator for &'a Row {
276 type Item = &'a Cell;
277 type IntoIter = Iter<'a, Cell>;
278 fn into_iter(self) -> Self::IntoIter {
279 self.iter()
280 }
281}
282
283impl<'a> IntoIterator for &'a mut Row {
292 type Item = &'a mut Cell;
293 type IntoIter = IterMut<'a, Cell>;
294 fn into_iter(self) -> Self::IntoIter {
295 self.iter_mut()
296 }
297}
298
299impl<S: ToString> Extend<S> for Row {
300 fn extend<T: IntoIterator<Item = S>>(&mut self, iter: T) {
301 self.cells
302 .extend(iter.into_iter().map(|s| Cell::new(&s.to_string())));
303 }
304}
305
306#[macro_export]
335macro_rules! row {
336 (($($out:tt)*);) => (vec![$($out)*]);
337 (($($out:tt)*); $value:expr) => (vec![$($out)* $crate::cell!($value)]);
338 (($($out:tt)*); $value:expr, $($n:tt)*) => ($crate::row!(($($out)* $crate::cell!($value),); $($n)*));
339 (($($out:tt)*); $style:ident -> $value:expr) => (vec![$($out)* $crate::cell!($style -> $value)]);
340 (($($out:tt)*); $style:ident -> $value:expr, $($n: tt)*) => ($crate::row!(($($out)* $crate::cell!($style -> $value),); $($n)*));
341
342 ($($content:expr), *) => ($crate::Row::new(vec![$($crate::cell!($content)), *])); ($style:ident => $($content:expr), *) => ($crate::Row::new(vec![$($crate::cell!($style -> $content)), *]));
344 ($style:ident => $($content:expr,) *) => ($crate::Row::new(vec![$($crate::cell!($style -> $content)), *]));
345 ($($content:tt)*) => ($crate::Row::new($crate::row!((); $($content)*)));
346}
347
348#[cfg(test)]
349mod tests {
350 use super::*;
351 use Cell;
352
353 #[test]
354 fn row_default_empty() {
355 let row1 = Row::default();
356 assert_eq!(row1.len(), 0);
357 assert!(row1.is_empty());
358 }
359
360 #[test]
361 fn get_add_set_cell() {
362 let mut row = Row::from(vec!["foo", "bar", "foobar"]);
363 assert_eq!(row.len(), 3);
364 assert!(row.get_mut_cell(12).is_none());
365 let c1 = row.get_mut_cell(0).unwrap().clone();
366 assert_eq!(c1.get_content(), "foo");
367
368 let c1 = Cell::from(&"baz");
369 assert!(row.set_cell(c1.clone(), 1000).is_err());
370 assert!(row.set_cell(c1.clone(), 0).is_ok());
371 assert_eq!(row.get_cell(0).unwrap().get_content(), "baz");
372
373 row.add_cell(c1.clone());
374 assert_eq!(row.len(), 4);
375 assert_eq!(row.get_cell(3).unwrap().get_content(), "baz");
376 }
377
378 #[test]
379 fn insert_cell() {
380 let mut row = Row::from(vec!["foo", "bar", "foobar"]);
381 assert_eq!(row.len(), 3);
382 let cell = Cell::new("baz");
383 row.insert_cell(1000, cell.clone());
384 assert_eq!(row.len(), 4);
385 assert_eq!(row.get_cell(3).unwrap().get_content(), "baz");
386 row.insert_cell(1, cell.clone());
387 assert_eq!(row.len(), 5);
388 assert_eq!(row.get_cell(1).unwrap().get_content(), "baz");
389 }
390
391 #[test]
392 fn remove_cell() {
393 let mut row = Row::from(vec!["foo", "bar", "foobar"]);
394 assert_eq!(row.len(), 3);
395 row.remove_cell(1000);
396 assert_eq!(row.len(), 3);
397 row.remove_cell(1);
398 assert_eq!(row.len(), 2);
399 assert_eq!(row.get_cell(0).unwrap().get_content(), "foo");
400 assert_eq!(row.get_cell(1).unwrap().get_content(), "foobar");
401 }
402
403 #[test]
404 fn extend_row() {
405 let mut row = Row::from(vec!["foo", "bar", "foobar"]);
406 row.extend(vec!["A", "B", "C"]);
407 assert_eq!(row.len(), 6);
408 assert_eq!(row.get_cell(3).unwrap().get_content(), "A");
409 assert_eq!(row.get_cell(4).unwrap().get_content(), "B");
410 assert_eq!(row.get_cell(5).unwrap().get_content(), "C");
411 }
412}