diff options
Diffstat (limited to 'src/xml/element.rs')
| -rw-r--r-- | src/xml/element.rs | 186 | 
1 files changed, 186 insertions, 0 deletions
| diff --git a/src/xml/element.rs b/src/xml/element.rs new file mode 100644 index 0000000..647fe90 --- /dev/null +++ b/src/xml/element.rs @@ -0,0 +1,186 @@ +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Elements +{ +    elements: Vec<Element>, +} + +impl Elements +{ +    pub fn get_first_tagged(&self) -> Option<&Tagged> +    { +        self.elements.iter().find_map(|element| match element { +            Element::Tagged(tagged_element) => Some(tagged_element), +            _ => None, +        }) +    } + +    pub fn get_first_tagged_with_name(&self, tag_name: &str) -> Option<&Tagged> +    { +        self.elements.iter().find_map(|element| match element { +            Element::Tagged(tagged_element) if tagged_element.name == tag_name => { +                Some(tagged_element) +            } +            _ => None, +        }) +    } + +    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_with_name(&self, tag_name: &str) -> Vec<&Tagged> +    { +        self.elements +            .iter() +            .filter_map(|element| match element { +                Element::Tagged(tagged_element) if tagged_element.name == tag_name => { +                    Some(tagged_element) +                } +                _ => None, +            }) +            .collect() +    } + +    pub fn get_first_text_element(&self) -> Option<&String> +    { +        self.elements.iter().find_map(|element| match element { +            Element::Text(text) => Some(text), +            _ => None, +        }) +    } + +    pub fn get_all_text_elements(&self) -> Vec<&String> +    { +        self.elements +            .iter() +            .filter_map(|element| match element { +                Element::Text(text) => Some(text), +                _ => None, +            }) +            .collect() +    } + +    pub fn has_tagged_element(&self, tag_name: &str) -> bool +    { +        self.elements.iter().any(|element| { +            matches!( +                element, +                Element::Tagged(tagged_element) if tagged_element.name == tag_name +            ) +        }) +    } +} + +impl<IntoIter: IntoIterator<Item = Element>> From<IntoIter> for Elements +{ +    fn from(into_iter: IntoIter) -> Self +    { +        Self { +            elements: into_iter.into_iter().collect(), +        } +    } +} + +impl<'elements> IntoIterator for &'elements Elements +{ +    type IntoIter = Iter<'elements>; +    type Item = &'elements Element; + +    fn into_iter(self) -> Self::IntoIter +    { +        Self::IntoIter { +            elements: self.elements.iter(), +        } +    } +} + +pub struct Iter<'elements> +{ +    elements: std::slice::Iter<'elements, Element>, +} + +impl<'elements> Iterator for Iter<'elements> +{ +    type Item = &'elements Element; + +    fn next(&mut self) -> Option<Self::Item> +    { +        self.elements.next() +    } +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum Element +{ +    Tagged(Tagged), +    Text(String), +    Comment(String), +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Tagged +{ +    name: String, +    child_elements: Elements, +    attributes: Vec<Attribute>, +} + +impl Tagged +{ +    pub fn new<Name, ChildElements, Attrs>( +        name: &Name, +        child_elements: ChildElements, +        attributes: Attrs, +    ) -> Self +    where +        Name: ToString, +        ChildElements: Into<Elements>, +        Attrs: IntoIterator<Item = Attribute>, +    { +        Self { +            name: name.to_string(), +            child_elements: child_elements.into(), +            attributes: attributes.into_iter().collect(), +        } +    } + +    pub fn name(&self) -> &str +    { +        &self.name +    } + +    pub fn child_elements(&self) -> &Elements +    { +        &self.child_elements +    } +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Attribute +{ +    pub key: String, +    pub value: Vec<u8>, +} + +pub trait FromElements: Sized +{ +    type Error; + +    fn from_elements(elements: &Elements) -> Result<Self, Self::Error>; +} | 
