evtx 0.1.1

A Fast (and safe) parser for the Windows XML Event Log (EVTX) format
Documentation
use crate::binxml::name::BinXmlName;
use crate::binxml::value_variant::BinXmlValue;

use log::error;
use std::borrow::Cow;

type Name<'a> = BinXmlName<'a>;

#[derive(Debug, PartialOrd, PartialEq, Clone)]
pub enum XmlModel<'a> {
    OpenElement(XmlElement<'a>),
    CloseElement,
    String(Cow<'a, str>),
    EndOfStream,
    StartOfStream,
}

pub struct XmlElementBuilder<'a> {
    name: Option<Name<'a>>,
    attributes: Vec<XmlAttribute<'a>>,
    current_attribute_name: Option<Name<'a>>,
    current_attribute_value: Option<Cow<'a, str>>,
}

impl<'a> XmlElementBuilder<'a> {
    pub fn new() -> Self {
        XmlElementBuilder {
            name: None,
            attributes: Vec::new(),
            current_attribute_name: None,
            current_attribute_value: None,
        }
    }
    pub fn name(mut self, name: Name<'a>) -> Self {
        self.name = Some(name);
        self
    }

    pub fn attribute_name(mut self, name: Name<'a>) -> Self {
        match self.current_attribute_name {
            None => self.current_attribute_name = Some(name),
            Some(name) => {
                error!("invalid state, overriding name");
                self.current_attribute_name = Some(name);
            }
        }
        self
    }

    pub fn attribute_value(mut self, value: BinXmlValue<'a>) -> Self {
        assert!(
            self.current_attribute_name.is_some(),
            "There should be a name"
        );
        match self.current_attribute_value {
            None => {
                self.current_attribute_value = Some(match value {
                    BinXmlValue::StringType(cow) => cow,
                    _ => Cow::Owned(format!("{:?}", value)),
                })
            }
            Some(_) => panic!("invalid state, there should not be a value"),
        }

        self.attributes.push(XmlAttribute {
            name: self.current_attribute_name.take().unwrap(),
            value: self.current_attribute_value.take().unwrap(),
        });

        self
    }

    pub fn finish(self) -> XmlElement<'a> {
        XmlElement {
            name: self.name.expect("Element name should be set"),
            attributes: self.attributes,
        }
    }
}

#[derive(Debug, PartialOrd, PartialEq, Clone)]
pub struct XmlAttribute<'a> {
    pub name: Name<'a>,
    pub value: Cow<'a, str>,
}

#[derive(Debug, PartialOrd, PartialEq, Clone)]
pub struct XmlElement<'a> {
    pub name: Name<'a>,
    pub attributes: Vec<XmlAttribute<'a>>,
}