1use serde::{Deserialize, Serialize};
4
5use super::Block;
6use super::location::Location;
7
8#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
10#[serde(rename_all = "lowercase")]
11pub enum HorizontalAlignment {
12 #[default]
13 Left,
14 Center,
15 Right,
16}
17
18#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
20#[serde(rename_all = "lowercase")]
21pub enum VerticalAlignment {
22 #[default]
23 Top,
24 Middle,
25 Bottom,
26}
27
28#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
30#[serde(rename_all = "lowercase")]
31#[non_exhaustive]
32pub enum ColumnWidth {
33 Proportional(u32),
35 Percentage(u32),
37 Auto,
39}
40
41impl Default for ColumnWidth {
42 fn default() -> Self {
43 ColumnWidth::Proportional(1)
44 }
45}
46
47#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
49#[serde(rename_all = "lowercase")]
50#[non_exhaustive]
51pub enum ColumnStyle {
52 #[serde(rename = "asciidoc")]
54 AsciiDoc,
55 #[default]
57 Default,
58 Emphasis,
60 Header,
62 Literal,
64 Monospace,
66 Strong,
68}
69
70#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
72#[non_exhaustive]
73pub struct ColumnFormat {
74 #[serde(default, skip_serializing_if = "is_default_halign")]
75 pub halign: HorizontalAlignment,
76 #[serde(default, skip_serializing_if = "is_default_valign")]
77 pub valign: VerticalAlignment,
78 #[serde(default, skip_serializing_if = "is_default_width")]
79 pub width: ColumnWidth,
80 #[serde(default, skip_serializing_if = "is_default_style")]
81 pub style: ColumnStyle,
82}
83
84impl ColumnFormat {
85 #[must_use]
87 pub fn new() -> Self {
88 Self::default()
89 }
90
91 #[must_use]
93 pub fn with_halign(mut self, halign: HorizontalAlignment) -> Self {
94 self.halign = halign;
95 self
96 }
97
98 #[must_use]
100 pub fn with_valign(mut self, valign: VerticalAlignment) -> Self {
101 self.valign = valign;
102 self
103 }
104
105 #[must_use]
107 pub fn with_width(mut self, width: ColumnWidth) -> Self {
108 self.width = width;
109 self
110 }
111
112 #[must_use]
114 pub fn with_style(mut self, style: ColumnStyle) -> Self {
115 self.style = style;
116 self
117 }
118}
119
120#[allow(clippy::trivially_copy_pass_by_ref)]
121fn is_default_halign(h: &HorizontalAlignment) -> bool {
122 *h == HorizontalAlignment::default()
123}
124
125#[allow(clippy::trivially_copy_pass_by_ref)]
126fn is_default_valign(v: &VerticalAlignment) -> bool {
127 *v == VerticalAlignment::default()
128}
129
130#[allow(clippy::trivially_copy_pass_by_ref)]
131fn is_default_width(w: &ColumnWidth) -> bool {
132 *w == ColumnWidth::default()
133}
134
135#[allow(clippy::trivially_copy_pass_by_ref)]
136fn is_default_style(s: &ColumnStyle) -> bool {
137 *s == ColumnStyle::default()
138}
139
140pub(crate) fn are_all_columns_default(specs: &[ColumnFormat]) -> bool {
141 specs.iter().all(|s| *s == ColumnFormat::default())
142}
143
144#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
146#[non_exhaustive]
147pub struct Table {
148 pub header: Option<TableRow>,
149 pub footer: Option<TableRow>,
150 pub rows: Vec<TableRow>,
151 #[serde(default, skip_serializing_if = "are_all_columns_default")]
154 pub columns: Vec<ColumnFormat>,
155 pub location: Location,
156}
157
158impl Table {
159 #[must_use]
161 pub fn new(rows: Vec<TableRow>, location: Location) -> Self {
162 Self {
163 header: None,
164 footer: None,
165 rows,
166 columns: Vec::new(),
167 location,
168 }
169 }
170
171 #[must_use]
173 pub fn with_header(mut self, header: Option<TableRow>) -> Self {
174 self.header = header;
175 self
176 }
177
178 #[must_use]
180 pub fn with_footer(mut self, footer: Option<TableRow>) -> Self {
181 self.footer = footer;
182 self
183 }
184
185 #[must_use]
187 pub fn with_columns(mut self, columns: Vec<ColumnFormat>) -> Self {
188 self.columns = columns;
189 self
190 }
191}
192
193#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
195#[non_exhaustive]
196pub struct TableRow {
197 pub columns: Vec<TableColumn>,
198}
199
200impl TableRow {
201 #[must_use]
203 pub fn new(columns: Vec<TableColumn>) -> Self {
204 Self { columns }
205 }
206}
207
208#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
210#[non_exhaustive]
211pub struct TableColumn {
212 pub content: Vec<Block>,
213}
214
215impl TableColumn {
216 #[must_use]
218 pub fn new(content: Vec<Block>) -> Self {
219 Self { content }
220 }
221}