Tom Alexander 397d4ea0bc
All checks were successful
rust-test Build rust-test has succeeded
rust-clippy Build rust-clippy has succeeded
build-natter Build build-natter has succeeded
format Build format has succeeded
Fix clippy issues.
2023-12-23 07:08:06 -05:00

101 lines
3.5 KiB
Rust

use super::macros::intermediate;
use super::table_row::ITableRow;
use crate::error::CustomError;
use crate::intermediate::table_group::ITableGroup;
use organic::types::StandardProperties;
#[derive(Debug, Clone)]
pub(crate) struct ITable {
pub(crate) children: Vec<ITableGroup>,
pub(crate) post_blank: organic::types::PostBlank,
}
intermediate!(
ITable,
&'orig organic::types::Table<'parse>,
original,
intermediate_context,
{
// Separate groups by lines, multiple contiguous lines are the same as one.
// If there is only one group, it is a tbody.
// If there are more than one group, the first is thead and the rest are tbody.
let sections = group_into_sections(&original.children);
let children = if sections.len() == 1 {
// If there is only one section, then it is a body.
let mut ret = Vec::new();
for group in sections.into_iter() {
let mut rows = Vec::new();
for obj in group.into_iter() {
rows.push(ITableRow::new(intermediate_context.clone(), obj).await?)
}
ret.push(ITableGroup::Body(rows));
}
ret
} else {
// If there are more than one section, the first is a head and the rest are body.
let mut ret = Vec::new();
let mut sections = sections.into_iter();
if let Some(group) = sections.next() {
let mut rows = Vec::new();
for obj in group.into_iter() {
rows.push(ITableRow::new(intermediate_context.clone(), obj).await?)
}
ret.push(ITableGroup::Head(rows));
}
for group in sections {
let mut rows = Vec::new();
for obj in group.into_iter() {
rows.push(ITableRow::new(intermediate_context.clone(), obj).await?)
}
ret.push(ITableGroup::Body(rows));
}
ret
};
Ok(ITable {
children,
post_blank: original.get_post_blank(),
})
}
);
enum GroupIntoSectionsState<'orig, 'parse> {
NonSection,
Section(Vec<&'orig organic::types::TableRow<'parse>>),
}
fn group_into_sections<'orig, 'parse>(
rows: &'orig [organic::types::TableRow<'parse>],
) -> Vec<Vec<&'orig organic::types::TableRow<'parse>>> {
let mut sections = Vec::new();
let mut rows = rows.iter();
let mut state = GroupIntoSectionsState::NonSection;
loop {
state = match (state, rows.next()) {
(GroupIntoSectionsState::NonSection, None) => break,
(GroupIntoSectionsState::NonSection, Some(row)) if row.children.is_empty() => {
GroupIntoSectionsState::NonSection
}
(GroupIntoSectionsState::NonSection, Some(row)) => {
GroupIntoSectionsState::Section(vec![row])
}
(GroupIntoSectionsState::Section(section), None) => {
sections.push(section);
break;
}
(GroupIntoSectionsState::Section(section), Some(row)) if row.children.is_empty() => {
sections.push(section);
GroupIntoSectionsState::NonSection
}
(GroupIntoSectionsState::Section(mut section), Some(row)) => {
section.push(row);
GroupIntoSectionsState::Section(section)
}
}
}
sections
}