diff options
author | HampusM <hampus@hampusmat.com> | 2023-03-04 13:18:33 +0100 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2023-03-04 13:18:33 +0100 |
commit | a15a878b87a4891ec856178c151faeaaa1799ad3 (patch) | |
tree | 8b72271476e8b4ca0cc89703d89ec736cd6febb8 /src | |
parent | f576587f8b872b6369c7079055944977f2293e5c (diff) |
feat: add table support
Diffstat (limited to 'src')
-rw-r--r-- | src/description.rs | 53 | ||||
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/table.rs (renamed from src/informal_table.rs) | 119 |
3 files changed, 125 insertions, 49 deletions
diff --git a/src/description.rs b/src/description.rs index e6cd1cd..615b0c2 100644 --- a/src/description.rs +++ b/src/description.rs @@ -1,6 +1,6 @@ //! Reference entry description. -use crate::informal_table::{Error as InformalTableError, InformalTable}; use crate::itemized_list::{Error as ItemizedListError, ItemizedList}; +use crate::table::{Error as TableError, Informal, Table}; use crate::variable_list::{Error as VariableListError, VariableList}; use crate::xml::element::{Element, Elements, FromElements, Tagged}; @@ -97,7 +97,7 @@ impl FromElements for Description .unwrap_or_default(), ))), "informaltable" => Some( - InformalTable::from_elements(part_elem.child_elements()) + Informal::from_elements(part_elem.child_elements()) .map(Part::InformalTable) .map_err(Self::Error::InvalidInformalTable), ), @@ -106,6 +106,11 @@ impl FromElements for Description .map(Part::ItemizedList) .map_err(Self::Error::InvalidItemizedList), ), + "table" => Some( + Table::from_elements(part_elem.child_elements()) + .map(Part::Table) + .map_err(Self::Error::InvalidTable), + ), "title" => None, name => Some(Err(Self::Error::UnknownPartFound(name.to_string()))), }) @@ -136,11 +141,15 @@ pub enum Error /// Invalid informal table. #[error("Invalid informal table")] - InvalidInformalTable(#[source] InformalTableError), + InvalidInformalTable(#[source] TableError), /// Invalid itemized list. #[error("Invalid itemized list")] InvalidItemizedList(#[source] ItemizedListError), + + /// Invalid table. + #[error("Invalid table")] + InvalidTable(#[source] TableError), } /// Description part. @@ -157,10 +166,13 @@ pub enum Part ProgramListing(String), /// Informal table. - InformalTable(InformalTable), + InformalTable(Informal), /// Itemized list. ItemizedList(ItemizedList), + + /// Table. + Table(Table), } /// Reference entry description paragraph. @@ -258,13 +270,16 @@ pub enum ParagraphPart ItemizedList(ItemizedList), /// Informal table part. - InformalTable(InformalTable), + InformalTable(Informal), /// Paragraph part. Paragraph(Paragraph), /// Footnote part. Footnote(Paragraph), + + /// Table part. + Table(Table), } impl FromElements for ParagraphPart @@ -300,11 +315,10 @@ impl ParagraphPart "inlineequation" => Self::InlineEquation, "programlisting" => Self::ProgramListing, "citerefentry" => Self::Entry, - "variablelist" | "itemizedlist" | "informaltable" | "para" | "footnote" => { - |_| { - unreachable!(); - } - } + "variablelist" | "itemizedlist" | "informaltable" | "para" | "footnote" + | "table" => |_| { + unreachable!(); + }, _ => { return Err(<Self as FromElements>::Error::UnknownPart( tagged_element.name().to_string(), @@ -341,10 +355,8 @@ impl ParagraphPart } if tagged_element.name() == "informaltable" { - let informal_table = InformalTable::from_elements( - tagged_element.child_elements(), - ) - .map_err(|err| ParagraphPartError::InvalidInformalTable(Box::new(err)))?; + let informal_table = Informal::from_elements(tagged_element.child_elements()) + .map_err(|err| ParagraphPartError::InvalidInformalTable(Box::new(err)))?; return Ok(Self::InformalTable(informal_table)); } @@ -373,6 +385,13 @@ impl ParagraphPart )); } + if tagged_element.name() == "table" { + let table = Table::from_elements(tagged_element.child_elements()) + .map_err(|err| ParagraphPartError::InvalidInformalTable(Box::new(err)))?; + + return Ok(Self::Table(table)); + } + let text_element = tagged_element .child_elements() .get_first_text_element() @@ -412,7 +431,7 @@ pub enum ParagraphPartError /// Invalid informal table. #[error("Invalid informal table")] - InvalidInformalTable(#[source] Box<InformalTableError>), + InvalidInformalTable(#[source] Box<TableError>), /// Invalid paragraph. #[error("Invalid paragraph")] @@ -421,4 +440,8 @@ pub enum ParagraphPartError /// Invalid footnote. #[error("Invalid footnote")] InvalidFootnote(#[source] Box<ParagraphError>), + + /// Invalid table. + #[error("Invalid table")] + InvalidTable(#[source] Box<TableError>), } @@ -14,8 +14,8 @@ use crate::xml::element::{Elements, FromElements}; use crate::xml::parser::{Error as ParserError, Parser}; pub mod description; -pub mod informal_table; pub mod itemized_list; +pub mod table; pub mod variable_list; mod xml; diff --git a/src/informal_table.rs b/src/table.rs index a940de4..b549b95 100644 --- a/src/informal_table.rs +++ b/src/table.rs @@ -1,25 +1,25 @@ -//! Informal table. +//! Tables. use crate::description::{Paragraph, ParagraphError}; use crate::xml::element::{Elements, FromElements, Tagged}; /// Informal table. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct InformalTable +pub struct Informal { - groups: Vec<TableGroup>, + groups: Vec<Group>, } -impl InformalTable +impl Informal { /// Returns the table groups. #[must_use] - pub fn groups(&self) -> &[TableGroup] + pub fn groups(&self) -> &[Group] { &self.groups } } -impl FromElements for InformalTable +impl FromElements for Informal { type Error = Error; @@ -28,34 +28,87 @@ impl FromElements for InformalTable let groups = elements .get_all_tagged_elements_with_name("tgroup") .into_iter() - .map(TableGroup::from_tagged_element) + .map(Group::from_tagged_element) .collect::<Result<Vec<_>, _>>()?; Ok(Self { groups }) } } -/// [`InformalTable`] error. +/// Table. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Table +{ + title: String, + groups: Vec<Group>, +} + +impl Table +{ + /// Returns the table title. + #[must_use] + pub fn title(&self) -> &str + { + &self.title + } + + /// Returns the table groups. + #[must_use] + pub fn groups(&self) -> &[Group] + { + &self.groups + } +} + +impl FromElements for Table +{ + type Error = Error; + + fn from_elements(elements: &Elements) -> Result<Self, Self::Error> + { + let title = elements + .get_first_tagged_with_name("title") + .ok_or(Self::Error::MissingTitle)? + .child_elements() + .get_first_text_element() + .cloned() + .unwrap_or_default(); + + let groups = elements + .get_all_tagged_elements_with_name("tgroup") + .into_iter() + .map(Group::from_tagged_element) + .collect::<Result<Vec<_>, _>>()?; + + Ok(Self { title, groups }) + } +} + +/// Table error. #[derive(Debug, thiserror::Error)] pub enum Error { /// Invalid group. #[error("Invalid group")] - InvalidGroup(#[from] TableGroupError), + InvalidGroup(#[from] GroupError), + + /// Missing title. + #[error("Missing title")] + MissingTitle, } /// Table group #[derive(Debug, Clone, PartialEq, Eq)] -pub struct TableGroup +pub struct Group { cols: u32, align: Option<String>, column_specs: Vec<ColumnSpec>, - head: Vec<TableRow>, - body: Vec<TableRow>, + head: Vec<Row>, + body: Vec<Row>, } -impl TableGroup +impl Group { /// Returns the column count. #[must_use] @@ -80,40 +133,40 @@ impl TableGroup /// Returns the head. #[must_use] - pub fn head(&self) -> &[TableRow] + pub fn head(&self) -> &[Row] { &self.head } /// Returns the body. #[must_use] - pub fn body(&self) -> &[TableRow] + pub fn body(&self) -> &[Row] { &self.body } } -impl TableGroup +impl Group { - fn from_tagged_element(element: &Tagged) -> Result<Self, TableGroupError> + fn from_tagged_element(element: &Tagged) -> Result<Self, GroupError> { let cols = String::from_utf8( element .attributes() .iter() .find(|attr| attr.key == "cols") - .ok_or(TableGroupError::MissingCols)? + .ok_or(GroupError::MissingCols)? .value .clone(), ) - .map_err(|_| TableGroupError::ColsNotUTF8)? + .map_err(|_| GroupError::ColsNotUTF8)? .parse::<u32>() - .map_err(|_| TableGroupError::ColsNotNumber)?; + .map_err(|_| GroupError::ColsNotNumber)?; let align = match element.attributes().iter().find(|attr| attr.key == "align") { Some(attr) => Some( String::from_utf8(attr.value.clone()) - .map_err(|_| TableGroupError::AlignNotUTF8)?, + .map_err(|_| GroupError::AlignNotUTF8)?, ), None => None, }; @@ -130,11 +183,11 @@ impl TableGroup let mut body = element .child_elements() .get_first_tagged_with_name("tbody") - .ok_or(TableGroupError::MissingBody)? + .ok_or(GroupError::MissingBody)? .child_elements() .get_all_tagged_elements_with_name("row") .into_iter() - .map(|row_element| TableRow::from_elements(row_element.child_elements())) + .map(|row_element| Row::from_elements(row_element.child_elements())) .collect::<Result<Vec<_>, _>>()?; let head = element @@ -148,7 +201,7 @@ impl TableGroup .get_all_tagged_elements_with_name("row") .into_iter() .map(|row_element| { - TableRow::from_elements(row_element.child_elements()) + Row::from_elements(row_element.child_elements()) }) .collect::<Result<Vec<_>, _>>() }, @@ -164,9 +217,9 @@ impl TableGroup } } -/// [`TableGroup`] error. +/// [`Group`] error. #[derive(Debug, thiserror::Error)] -pub enum TableGroupError +pub enum GroupError { /// Missing cols element attribute. #[error("Missing cols")] @@ -182,7 +235,7 @@ pub enum TableGroupError /// Invalid row. #[error("Invalid row")] - InvalidRow(#[from] TableRowError), + InvalidRow(#[from] RowError), /// Cols is not valid UTF-8. #[error("Cols is not valid UTF-8")] @@ -302,12 +355,12 @@ pub enum ColumnSpecError /// Table row. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct TableRow +pub struct Row { entries: Vec<Paragraph>, } -impl TableRow +impl Row { /// Returns the entries. #[must_use] @@ -317,9 +370,9 @@ impl TableRow } } -impl FromElements for TableRow +impl FromElements for Row { - type Error = TableRowError; + type Error = RowError; fn from_elements(elements: &Elements) -> Result<Self, Self::Error> { @@ -333,9 +386,9 @@ impl FromElements for TableRow } } -/// [`TableRow`] error. +/// [`Row`] error. #[derive(Debug, thiserror::Error)] -pub enum TableRowError +pub enum RowError { /// Invalid paragraph. #[error("Invalid paragraph")] |