use std::{fmt::Display, io::Write};
use crate::{
file::csv::{RowData, WriteRow},
table::cell::{Align, Cell, Style},
};
#[derive(Default)]
pub struct Row {
cells: Vec<Cell>,
max_len: usize,
}
#[derive(PartialEq)]
pub enum ColumnJoinType {
Normal,
Spaced,
Plus,
}
impl Row {
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool {
self.cells.is_empty()
}
#[inline]
#[must_use]
pub fn len(&self) -> usize {
self.cells.len()
}
#[inline]
#[must_use]
pub fn push<T>(mut self, value: T, align: Align, style: Style) -> Self
where
T: Display,
{
let value = value.to_string();
let len = value.len();
let cell = Cell::new(value, align, style);
if len > self.max_len {
self.max_len = len;
}
self.cells.push(cell);
self
}
#[inline]
#[must_use]
pub fn blank(self) -> Self {
self.push("", Align::Left, Style::Normal)
}
#[inline]
#[must_use]
pub fn size(&self) -> usize {
self.to_string(None, ColumnJoinType::Spaced).len()
}
#[inline]
#[must_use]
pub fn get_column_size(&self, index: usize) -> usize {
assert!(index < self.cells.len(), "Invalid column index.");
self.cells[index].size()
}
#[inline]
pub fn print(&self, stdout: &mut impl Write, sizes: &Vec<usize>, join_type: ColumnJoinType) {
writeln!(stdout, "{}", self.to_string(Some(sizes), join_type)).unwrap();
}
#[must_use]
fn to_string(&self, sizes: Option<&Vec<usize>>, join_type: ColumnJoinType) -> String {
let join_str = match join_type {
ColumnJoinType::Normal => "|",
ColumnJoinType::Spaced => " | ",
ColumnJoinType::Plus => "+",
};
let line = self
.cells
.iter()
.enumerate()
.map(|(index, cell)| {
let size = match sizes {
Some(sizes) => sizes[index],
None => cell.size(),
};
cell.to_sized_string(size)
})
.collect::<Vec<String>>()
.join(join_str);
if join_type == ColumnJoinType::Spaced {
format!("| {line} |")
} else {
format!("|{line}|")
}
}
}
impl WriteRow for Row {
fn as_row(&self, row_data: &mut RowData) {
for cell in &self.cells {
row_data.push(cell.value());
}
}
}