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),
}