use error::Error;
use quick_xml::{Element, Event, XmlWriter};
use quick_xml::error::Error as XmlError;
use std::collections::HashMap;
use toxml::ToXml;
pub mod itunes;
pub mod dublincore;
pub type ExtensionMap = HashMap<String, HashMap<String, Vec<Extension>>>;
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Extension {
name: String,
value: Option<String>,
attrs: HashMap<String, String>,
children: HashMap<String, Vec<Extension>>,
}
impl Extension {
pub fn name(&self) -> &str {
self.name.as_str()
}
pub fn value(&self) -> Option<&str> {
self.value.as_ref().map(|s| s.as_str())
}
pub fn attrs(&self) -> &HashMap<String, String> {
&self.attrs
}
pub fn children(&self) -> &HashMap<String, Vec<Extension>> {
&self.children
}
}
impl ToXml for Extension {
fn to_xml<W: ::std::io::Write>(&self, writer: &mut XmlWriter<W>) -> Result<(), XmlError> {
let element = Element::new(&self.name);
writer
.write(Event::Start({
let mut element = element.clone();
element.extend_attributes(&self.attrs);
element
}))?;
if let Some(value) = self.value.as_ref() {
writer.write(Event::Text(Element::new(value)))?;
}
for extensions in self.children.values() {
for extension in extensions {
extension.to_xml(writer)?;
}
}
writer.write(Event::End(element))
}
}
#[derive(Debug, Default, Clone)]
pub struct ExtensionBuilder {
name: String,
value: Option<String>,
attrs: HashMap<String, String>,
children: HashMap<String, Vec<Extension>>,
}
impl ExtensionBuilder {
pub fn new() -> ExtensionBuilder {
ExtensionBuilder::default()
}
pub fn name(mut self, name: &str) -> ExtensionBuilder {
self.name = name.to_string();
self
}
pub fn value(mut self, value: Option<String>) -> ExtensionBuilder {
self.value = value;
self
}
pub fn attrs(mut self, attrs: HashMap<String, String>) -> ExtensionBuilder {
self.attrs = attrs;
self
}
pub fn children(mut self, children: HashMap<String, Vec<Extension>>) -> ExtensionBuilder {
self.children = children;
self
}
pub fn finalize(self) -> Result<Extension, Error> {
Ok(Extension {
name: self.name,
value: self.value,
attrs: self.attrs,
children: self.children,
})
}
}
pub fn get_extension_value<'a>(map: &'a HashMap<String, Vec<Extension>>,
key: &str)
-> Option<&'a str> {
map.get(key)
.and_then(|v| v.first())
.and_then(|ext| ext.value.as_ref())
.map(|s| s.as_str())
}
pub fn remove_extension_value(map: &mut HashMap<String, Vec<Extension>>,
key: &str)
-> Option<String> {
map.remove(key)
.map(|mut v| v.remove(0))
.and_then(|ext| ext.value)
}
pub fn get_extension_values<'a>(map: &'a HashMap<String, Vec<Extension>>,
key: &str)
-> Option<Vec<&'a str>> {
map.get(key)
.map(|v| {
v.iter()
.filter_map(|ext| ext.value.as_ref().map(|s| s.as_str()))
.collect::<Vec<_>>()
})
}
pub fn remove_extension_values(map: &mut HashMap<String, Vec<Extension>>,
key: &str)
-> Option<Vec<String>> {
map.remove(key)
.map(|v| {
v.into_iter()
.filter_map(|ext| ext.value)
.collect::<Vec<_>>()
})
}