summaryrefslogtreecommitdiff
path: root/src/description
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2023-05-16 21:59:46 +0200
committerHampusM <hampus@hampusmat.com>2023-05-16 21:59:46 +0200
commitcc30a537284871d668911353bd121e38d0353eb0 (patch)
tree121976a44346f5979447d9d9052372246d4ff66c /src/description
parentb336066d6067a0eb9ff9fc34c5aa062b86e56c62 (diff)
refactor: reorganize structsHEADmaster
Diffstat (limited to 'src/description')
-rw-r--r--src/description/mod.rs98
-rw-r--r--src/description/part.rs104
2 files changed, 202 insertions, 0 deletions
diff --git a/src/description/mod.rs b/src/description/mod.rs
new file mode 100644
index 0000000..a87c1cf
--- /dev/null
+++ b/src/description/mod.rs
@@ -0,0 +1,98 @@
+//! Reference entry description.
+use crate::xml::element::{Elements, FromElements};
+
+mod part;
+
+pub use part::{Error as PartError, Part};
+
+/// Reference entry description.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Description
+{
+ for_function: Option<String>,
+ parts: Vec<Part>,
+}
+
+impl Description
+{
+ /// Returns a new empty `Description`.
+ #[must_use]
+ pub fn new() -> Self
+ {
+ Self {
+ for_function: None,
+ parts: Vec::new(),
+ }
+ }
+
+ /// Returns what function this description is specific for.
+ #[must_use]
+ pub fn for_function(&self) -> &Option<String>
+ {
+ &self.for_function
+ }
+
+ /// Returns the description's parts.
+ #[must_use]
+ pub fn parts(&self) -> &[Part]
+ {
+ &self.parts
+ }
+}
+
+impl Default for Description
+{
+ fn default() -> Self
+ {
+ Self::new()
+ }
+}
+
+impl FromElements for Description
+{
+ type Error = Error;
+
+ fn from_elements(elements: &Elements) -> Result<Self, Self::Error>
+ {
+ let for_function =
+ elements
+ .get_first_tagged_with_name("title")
+ .and_then(|title_element| {
+ let title_text =
+ title_element.child_elements().get_first_text_element()?;
+
+ if title_text != "Description for " {
+ return None;
+ }
+
+ let function_element = title_element
+ .child_elements()
+ .get_first_tagged_with_name("function")?;
+
+ function_element
+ .child_elements()
+ .get_first_text_element()
+ .cloned()
+ });
+
+ let parts = elements
+ .get_all_tagged_elements()
+ .into_iter()
+ .map(Part::from_tagged_element)
+ .collect::<Result<Vec<_>, _>>()?;
+
+ Ok(Description {
+ for_function,
+ parts,
+ })
+ }
+}
+
+/// [`Description`] error.
+#[derive(Debug, thiserror::Error)]
+pub enum Error
+{
+ /// Invalid description part.
+ #[error("Invalid description part")]
+ InvalidPart(#[from] PartError),
+}
diff --git a/src/description/part.rs b/src/description/part.rs
new file mode 100644
index 0000000..2f1771f
--- /dev/null
+++ b/src/description/part.rs
@@ -0,0 +1,104 @@
+use crate::gloss_list::{Error as GlossListError, GlossList};
+use crate::itemized_list::{Error as ItemizedListError, ItemizedList};
+use crate::paragraph::{Error as ParagraphError, Paragraph};
+use crate::table::{Error as TableError, Informal, Table};
+use crate::variable_list::{Error as VariableListError, VariableList};
+use crate::xml::element::{FromElements, Tagged};
+
+/// Description part.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum Part
+{
+ /// Paragraph.
+ Paragraph(Paragraph),
+
+ /// Variable list.
+ VariableList(VariableList),
+
+ /// Program listing.
+ ProgramListing(String),
+
+ /// Informal table.
+ InformalTable(Informal),
+
+ /// Itemized list.
+ ItemizedList(ItemizedList),
+
+ /// Table.
+ Table(Table),
+
+ /// Gloss list.
+ GlossList(GlossList),
+}
+
+impl Part
+{
+ pub(crate) fn from_tagged_element(tagged_element: &Tagged) -> Result<Self, Error>
+ {
+ match tagged_element.name() {
+ "para" => Paragraph::from_elements(tagged_element.child_elements())
+ .map(Part::Paragraph)
+ .map_err(Error::InvalidParagraph),
+ "variablelist" => {
+ VariableList::from_elements(tagged_element.child_elements())
+ .map(Part::VariableList)
+ .map_err(Error::InvalidVariableList)
+ }
+ "programlisting" => Ok(Part::ProgramListing(
+ tagged_element
+ .child_elements()
+ .get_first_text_element()
+ .cloned()
+ .unwrap_or_default(),
+ )),
+ "informaltable" => Informal::from_elements(tagged_element.child_elements())
+ .map(Part::InformalTable)
+ .map_err(Error::InvalidInformalTable),
+ "itemizedlist" => {
+ ItemizedList::from_elements(tagged_element.child_elements())
+ .map(Part::ItemizedList)
+ .map_err(Error::InvalidItemizedList)
+ }
+ "table" => Table::from_elements(tagged_element.child_elements())
+ .map(Part::Table)
+ .map_err(Error::InvalidTable),
+ "glosslist" => GlossList::from_elements(tagged_element.child_elements())
+ .map(Part::GlossList)
+ .map_err(Error::InvalidGlossList),
+ name => Err(Error::Unknown(name.to_string())),
+ }
+ }
+}
+
+/// [`Part`] error.
+#[derive(Debug, thiserror::Error)]
+pub enum Error
+{
+ /// Unknown description part.
+ #[error("Unknown description part '{0}'")]
+ Unknown(String),
+
+ /// Invalid paragraph.
+ #[error("Invalid paragraph")]
+ InvalidParagraph(#[source] ParagraphError),
+
+ /// Invalid variable list.
+ #[error("Invalid variable list")]
+ InvalidVariableList(#[source] VariableListError),
+
+ /// Invalid informal table.
+ #[error("Invalid informal table")]
+ InvalidInformalTable(#[source] TableError),
+
+ /// Invalid itemized list.
+ #[error("Invalid itemized list")]
+ InvalidItemizedList(#[source] ItemizedListError),
+
+ /// Invalid table.
+ #[error("Invalid table")]
+ InvalidTable(#[source] TableError),
+
+ /// Invalid gloss list.
+ #[error("Invalid gloss list")]
+ InvalidGlossList(#[source] GlossListError),
+}