From 11c39d50411a747eedac4c6a16fedf598ae798f5 Mon Sep 17 00:00:00 2001 From: HampusM Date: Thu, 23 Feb 2023 22:35:06 +0100 Subject: feat: add project & getting function entries --- src/description.rs | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 src/description.rs (limited to 'src/description.rs') diff --git a/src/description.rs b/src/description.rs new file mode 100644 index 0000000..ba37abc --- /dev/null +++ b/src/description.rs @@ -0,0 +1,211 @@ +//! Reference entry description. +use crate::util::enum_with_get_inner; +use crate::xml::element::{Elements, FromElements, Tagged}; + +/// Reference entry description. +#[derive(Debug)] +pub struct Description +{ + paragraphs: Vec, +} + +impl Description +{ + /// Returns a new `ReferenceDescription`. + #[must_use] + pub fn new() -> Self + { + Self { + paragraphs: Vec::new(), + } + } + + /// Returns the reference description's paragraphs. + #[must_use] + pub fn paragraphs(&self) -> &[Paragraph] + { + &self.paragraphs + } +} + +impl Default for Description +{ + fn default() -> Self + { + Self::new() + } +} + +impl FromElements for Description +{ + type Error = Error; + + fn from_elements(elements: &Elements) -> Result + { + let paragraphs = elements + .get_all_tagged_elements_with_name("para") + .into_iter() + .map(|paragraph_element| { + Paragraph::from_elements(paragraph_element.child_elements()) + }) + .collect::, _>>()?; + + Ok(Description { paragraphs }) + } +} + +/// [`Description`] error. +#[derive(Debug, thiserror::Error)] +pub enum Error +{ + /// Invalid paragraph. + #[error("Invalid paragraph")] + InvalidParagraph(#[from] ParagraphError), +} + +/// Reference entry description paragraph. +#[derive(Debug)] +pub struct Paragraph +{ + parts: Vec, +} + +impl Paragraph +{ + /// Returns the parts of the paragraph. + #[must_use] + pub fn parts(&self) -> &[ParagraphPart] + { + &self.parts + } +} + +impl FromElements for Paragraph +{ + type Error = ParagraphError; + + fn from_elements(elements: &Elements) -> Result + { + let parts = elements + .into_iter() + .map(|element| { + ParagraphPart::from_elements(&Elements::from([element.clone()])) + }) + .collect::, _>>()?; + + Ok(Self { parts }) + } +} + +/// [`Paragraph`] error. +#[derive(Debug, thiserror::Error)] +pub enum ParagraphError +{ + /// Invalid reference description part. + #[error("Invalid part")] + InvalidPart(#[from] ParagraphPartError), +} + +enum_with_get_inner! { +inner = String; + +/// Reference entry description paragraph part. +#[derive(Debug)] +pub enum ParagraphPart +{ + /// Text part. + Text(String), + + /// .. part. + Constant(String), + + /// .. part. + Function(String), + + /// .. part. + Parameter(String), + + /// Reference entry citation part. + Entry(String), +} +} + +impl FromElements for ParagraphPart +{ + type Error = ParagraphPartError; + + 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::InputIsComment)?; + + Ok(Self::Text(text.clone())) + } +} + +impl ParagraphPart +{ + 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, + "citerefentry" => Self::Entry, + _ => { + 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())); + } + + let text_element = tagged_element + .child_elements() + .get_first_text_element() + .ok_or(::Error::NoTextInTagged)?; + + Ok(create(text_element.clone())) + } +} + +/// [`ParagraphPart`] error. +#[derive(Debug, thiserror::Error)] +pub enum ParagraphPartError +{ + /// Input element is a comment. + #[error("Input element is a comment")] + InputIsComment, + + /// A input element is a unknown reference description part. + #[error("Input element with name '{0}' is a unknown reference description 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, +} -- cgit v1.2.3-18-g5258