use crate::emphasis::{Emphasis, Error as EmphasisError}; use crate::itemized_list::{Error as ItemizedListError, ItemizedList}; use crate::paragraph::{Error as ParagraphError, Paragraph}; use crate::table::{Error as TableError, Informal as InformalTable, Table}; use crate::variable_list::{Error as VariableListError, VariableList}; use crate::xml::element::{Elements, FromElements, Tagged}; /// Paragraph part. #[derive(Debug, Clone, PartialEq, Eq)] pub enum Part { /// Text part. Text(String), /// .. part. Constant(String), /// .. part. Function(String), /// .. part. Parameter(String), /// Emphasis part. Emphasis(Emphasis), /// Code part. Code(String), /// Inline equation part. InlineEquation(String), /// Program listing part. ProgramListing(String), /// Reference entry citation part. Entry(String), /// Variable list part. VariableList(VariableList), /// Itemized list part. ItemizedList(ItemizedList), /// Informal table part. InformalTable(InformalTable), /// Paragraph part. Paragraph(Paragraph), /// Footnote part. Footnote(Paragraph), /// Table part. Table(Table), /// Informal equation part. InformalEquation(String), /// Superscript part. Superscript(String), } impl FromElements for Part { type Error = Error; fn from_elements(elements: &Elements) -> Result { if let Some(tagged_element) = elements.get_first_tagged() { return Self::from_tagged_element(tagged_element); } let text = elements .get_first_text_element() .ok_or(Self::Error::ExpectedTextElement)?; Ok(Self::Text(text.clone())) } } impl Part { fn from_tagged_element( tagged_element: &Tagged, ) -> Result::Error> { let create: fn(String) -> Self = match tagged_element.name() { "constant" => Self::Constant, "function" => Self::Function, "parameter" => Self::Parameter, "code" => Self::Code, "inlineequation" => Self::InlineEquation, "programlisting" => Self::ProgramListing, "citerefentry" => Self::Entry, "superscript" => Self::Superscript, "variablelist" | "itemizedlist" | "informaltable" | "para" | "footnote" | "table" | "informalequation" | "emphasis" => |_| { unreachable!(); }, _ => { return Err(::Error::UnknownPart( tagged_element.name().to_string(), )); } }; if tagged_element.name() == "citerefentry" { let title_element = tagged_element .child_elements() .get_first_tagged_with_name("refentrytitle") .ok_or(::Error::NoEntryTitleFound)?; let title = title_element .child_elements() .get_first_text_element() .ok_or(::Error::NoTextInTagged)?; return Ok(Self::Entry(title.clone())); } if tagged_element.name() == "variablelist" { let variable_list = VariableList::from_elements(tagged_element.child_elements())?; return Ok(Self::VariableList(variable_list)); } if tagged_element.name() == "itemizedlist" { let itemized_list = ItemizedList::from_elements(tagged_element.child_elements())?; return Ok(Self::ItemizedList(itemized_list)); } if tagged_element.name() == "informaltable" { let informal_table = InformalTable::from_elements(tagged_element.child_elements()) .map_err(|err| Error::InvalidInformalTable(Box::new(err)))?; return Ok(Self::InformalTable(informal_table)); } if tagged_element.name() == "inlineequation" { return Ok(Self::InlineEquation( tagged_element .child_elements() .into_iter() .map(ToString::to_string) .collect::(), )); } if tagged_element.name() == "para" { return Ok(Self::Paragraph( Paragraph::from_elements(tagged_element.child_elements()) .map_err(|err| Error::InvalidParagraph(Box::new(err)))?, )); } if tagged_element.name() == "footnote" { return Ok(Self::Footnote( Paragraph::from_elements(tagged_element.child_elements()) .map_err(|err| Error::InvalidFootnote(Box::new(err)))?, )); } if tagged_element.name() == "table" { let table = Table::from_elements(tagged_element.child_elements()) .map_err(|err| Error::InvalidInformalTable(Box::new(err)))?; return Ok(Self::Table(table)); } if tagged_element.name() == "informalequation" { return Ok(Self::InlineEquation( tagged_element .child_elements() .into_iter() .map(ToString::to_string) .collect::(), )); } if tagged_element.name() == "emphasis" { return Ok(Self::Emphasis(Emphasis::from_tagged_element( tagged_element, )?)); } let text_element = tagged_element .child_elements() .get_first_text_element() .ok_or(::Error::NoTextInTagged)?; Ok(create(text_element.clone())) } } /// [`Part`] error. #[derive(Debug, thiserror::Error)] pub enum Error { /// Expected a text element. #[error("Expected a text element")] ExpectedTextElement, /// A input element is a unknown paragraph part. #[error("Input element with name '{0}' is a unknown paragraph part")] UnknownPart(String), /// No text was found in tagged input element. #[error("No text was found in tagged input element")] NoTextInTagged, /// No entry title found. #[error("No entry title found")] NoEntryTitleFound, /// Invalid variable list. #[error("Invalid variable list")] InvalidVariableList(#[from] VariableListError), /// Invalid itemized list. #[error("Invalid itemized list")] InvalidItemizedList(#[from] ItemizedListError), /// Invalid informal table. #[error("Invalid informal table")] InvalidInformalTable(#[source] Box), /// Invalid paragraph. #[error("Invalid paragraph")] InvalidParagraph(#[source] Box), /// Invalid footnote. #[error("Invalid footnote")] InvalidFootnote(#[source] Box), /// Invalid table. #[error("Invalid table")] InvalidTable(#[source] Box), /// Invalid emphasis. #[error("Invalid emphasis")] InvalidEmphasis(#[from] EmphasisError), }