diff options
-rw-r--r-- | src/description.rs | 41 | ||||
-rw-r--r-- | src/lib.rs | 46 | ||||
-rw-r--r-- | src/xml/element.rs | 40 |
3 files changed, 84 insertions, 43 deletions
diff --git a/src/description.rs b/src/description.rs index f536b4f..ccd95b2 100644 --- a/src/description.rs +++ b/src/description.rs @@ -7,16 +7,27 @@ use crate::xml::element::{Elements, FromElements, Tagged}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Description { + for_function: Option<String>, parts: Vec<Part>, } impl Description { - /// Returns a new `ReferenceDescription`. + /// Returns a new empty `Description`. #[must_use] pub fn new() -> Self { - Self { parts: Vec::new() } + 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. @@ -41,6 +52,27 @@ impl FromElements for Description 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() @@ -61,7 +93,10 @@ impl FromElements for Description }) .collect::<Result<Vec<_>, Self::Error>>()?; - Ok(Description { parts }) + Ok(Description { + for_function, + parts, + }) } } @@ -10,7 +10,7 @@ use std::os::unix::prelude::OsStrExt; use include_dir::{include_dir, Dir}; use crate::description::{Description, Error as DescriptionError}; -use crate::xml::element::{Attribute, Elements, FromElements}; +use crate::xml::element::{Elements, FromElements}; use crate::xml::parser::{Error as ParserError, Parser}; pub mod description; @@ -26,17 +26,20 @@ static GL4_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/OpenGL-Refpages/gl4"); pub struct ReferenceEntry { purpose: String, - description: Description, + descriptions: Vec<Description>, } impl ReferenceEntry { /// Returns a new `ReferenceEntry`. - pub fn new(purpose: &impl ToString, description: Description) -> Self + pub fn new( + purpose: &impl ToString, + descriptions: impl IntoIterator<Item = Description>, + ) -> Self { Self { purpose: purpose.to_string(), - description, + descriptions: descriptions.into_iter().collect(), } } @@ -106,11 +109,11 @@ impl ReferenceEntry &self.purpose } - /// Returns the reference entry description. + /// Returns the reference entry descriptions. #[must_use] - pub fn description(&self) -> &Description + pub fn descriptions(&self) -> &[Description] { - &self.description + &self.descriptions } } @@ -140,23 +143,26 @@ impl FromElements for ReferenceEntry .cloned() .unwrap_or_default(); - let description_refsect = refentry_element + let description_elements = refentry_element .child_elements() - .get_first_tagged_with_name_and_attr( - "refsect1", - &Attribute { - key: "xml:id".to_string(), - value: b"description".to_vec(), - }, - ) - .ok_or(Self::Error::MissingDescriptionRefSect)?; - - let description = - Description::from_elements(description_refsect.child_elements())?; + .get_all_tagged_with_name_and_attr("refsect1", |attr| { + attr.key == "xml:id" && attr.value.starts_with(b"description") + }); + + if description_elements.is_empty() { + return Err(Self::Error::MissingDescriptionRefSect); + } + + let descriptions = description_elements + .iter() + .map(|description_element| { + Description::from_elements(description_element.child_elements()) + }) + .collect::<Result<Vec<_>, _>>()?; Ok(ReferenceEntry { purpose, - description, + descriptions, }) } } diff --git a/src/xml/element.rs b/src/xml/element.rs index b778dac..91e4130 100644 --- a/src/xml/element.rs +++ b/src/xml/element.rs @@ -24,26 +24,6 @@ impl Elements }) } - pub fn get_first_tagged_with_name_and_attr( - &self, - tag_name: &str, - attribute: &Attribute, - ) -> Option<&Tagged> - { - self.elements.iter().find_map(|element| match element { - Element::Tagged(tagged_element) - if tagged_element.name == tag_name - && tagged_element - .attributes - .iter() - .any(|attr| attr == attribute) => - { - Some(tagged_element) - } - _ => None, - }) - } - pub fn get_all_tagged_elements(&self) -> Vec<&Tagged> { self.elements @@ -68,6 +48,26 @@ impl Elements .collect() } + pub fn get_all_tagged_with_name_and_attr( + &self, + tag_name: &str, + attr_is_match: fn(&Attribute) -> bool, + ) -> Vec<&Tagged> + { + self.elements + .iter() + .filter_map(|element| match element { + Element::Tagged(tagged_element) + if tagged_element.name == tag_name + && tagged_element.attributes.iter().any(attr_is_match) => + { + Some(tagged_element) + } + _ => None, + }) + .collect() + } + pub fn get_first_text_element(&self) -> Option<&String> { self.elements.iter().find_map(|element| match element { |