use serde::Serialize;
use super::Block;
use super::location::Location;
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum HorizontalAlignment {
#[default]
Left,
Center,
Right,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum VerticalAlignment {
#[default]
Top,
Middle,
Bottom,
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize)]
#[serde(rename_all = "lowercase")]
#[non_exhaustive]
pub enum ColumnWidth {
Proportional(u32),
Percentage(u32),
Auto,
}
impl Default for ColumnWidth {
fn default() -> Self {
ColumnWidth::Proportional(1)
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize)]
#[serde(rename_all = "lowercase")]
#[non_exhaustive]
pub enum ColumnStyle {
#[serde(rename = "asciidoc")]
AsciiDoc,
#[default]
Default,
Emphasis,
Header,
Literal,
Monospace,
Strong,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
#[non_exhaustive]
pub struct ColumnFormat {
#[serde(default, skip_serializing_if = "is_default_halign")]
pub halign: HorizontalAlignment,
#[serde(default, skip_serializing_if = "is_default_valign")]
pub valign: VerticalAlignment,
#[serde(default, skip_serializing_if = "is_default_width")]
pub width: ColumnWidth,
#[serde(default, skip_serializing_if = "is_default_style")]
pub style: ColumnStyle,
}
impl ColumnFormat {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn with_halign(mut self, halign: HorizontalAlignment) -> Self {
self.halign = halign;
self
}
#[must_use]
pub fn with_valign(mut self, valign: VerticalAlignment) -> Self {
self.valign = valign;
self
}
#[must_use]
pub fn with_width(mut self, width: ColumnWidth) -> Self {
self.width = width;
self
}
#[must_use]
pub fn with_style(mut self, style: ColumnStyle) -> Self {
self.style = style;
self
}
}
#[allow(clippy::trivially_copy_pass_by_ref)]
fn is_default_halign(h: &HorizontalAlignment) -> bool {
*h == HorizontalAlignment::default()
}
#[allow(clippy::trivially_copy_pass_by_ref)]
fn is_default_valign(v: &VerticalAlignment) -> bool {
*v == VerticalAlignment::default()
}
#[allow(clippy::trivially_copy_pass_by_ref)]
fn is_default_width(w: &ColumnWidth) -> bool {
*w == ColumnWidth::default()
}
#[allow(clippy::trivially_copy_pass_by_ref)]
fn is_default_style(s: &ColumnStyle) -> bool {
*s == ColumnStyle::default()
}
pub(crate) fn are_all_columns_default(specs: &[ColumnFormat]) -> bool {
specs.iter().all(|s| *s == ColumnFormat::default())
}
#[derive(Clone, Debug, PartialEq, Serialize)]
#[non_exhaustive]
pub struct Table {
pub header: Option<TableRow>,
pub footer: Option<TableRow>,
pub rows: Vec<TableRow>,
#[serde(default, skip_serializing_if = "are_all_columns_default")]
pub columns: Vec<ColumnFormat>,
pub location: Location,
}
impl Table {
#[must_use]
pub fn new(rows: Vec<TableRow>, location: Location) -> Self {
Self {
header: None,
footer: None,
rows,
columns: Vec::new(),
location,
}
}
#[must_use]
pub fn with_header(mut self, header: Option<TableRow>) -> Self {
self.header = header;
self
}
#[must_use]
pub fn with_footer(mut self, footer: Option<TableRow>) -> Self {
self.footer = footer;
self
}
#[must_use]
pub fn with_columns(mut self, columns: Vec<ColumnFormat>) -> Self {
self.columns = columns;
self
}
}
#[derive(Clone, Debug, PartialEq, Serialize)]
#[non_exhaustive]
pub struct TableRow {
pub columns: Vec<TableColumn>,
}
impl TableRow {
#[must_use]
pub fn new(columns: Vec<TableColumn>) -> Self {
Self { columns }
}
}
#[derive(Clone, Debug, PartialEq, Serialize)]
#[non_exhaustive]
pub struct TableColumn {
pub content: Vec<Block>,
#[serde(skip_serializing_if = "is_default_span")]
pub colspan: usize,
#[serde(skip_serializing_if = "is_default_span")]
pub rowspan: usize,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub halign: Option<HorizontalAlignment>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub valign: Option<VerticalAlignment>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub style: Option<ColumnStyle>,
}
#[allow(clippy::trivially_copy_pass_by_ref)]
const fn is_default_span(span: &usize) -> bool {
*span == 1
}
impl TableColumn {
#[must_use]
pub(crate) fn with_format(
content: Vec<Block>,
colspan: usize,
rowspan: usize,
halign: Option<HorizontalAlignment>,
valign: Option<VerticalAlignment>,
style: Option<ColumnStyle>,
) -> Self {
Self {
content,
colspan,
rowspan,
halign,
valign,
style,
}
}
}