use std::fmt;
use std::borrow::Cow;
use escape::Escaped;
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Attribute<'a> {
pub name: Cow<'a, str>,
pub value: Cow<'a, str>,
}
impl<'a> Attribute<'a> {
pub fn new<N, V>(name: N, value: V) -> Attribute<'a>
where N: Into<Cow<'a, str>>,
V: Into<Cow<'a, str>>
{
Attribute {
name: name.into(),
value: value.into(),
}
}
}
impl<'a> fmt::Display for Attribute<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.value == "" {
write!(f, "{}", self.name)
} else {
write!(f, "{}=\"{}\"", self.name.as_ref(), Escaped(&self.value))
}
}
}
#[derive(Clone, Debug, Eq)]
pub struct AttributeList<'a>(Cow<'a, [Attribute<'a>]>);
impl<'a> AttributeList<'a> {
pub fn empty() -> AttributeList<'a> {
AttributeList(Cow::Borrowed(&[]))
}
pub fn from_vec(attrs: Vec<Attribute<'a>>) -> AttributeList<'a> {
AttributeList(Cow::Owned(attrs))
}
pub fn into_vec(self) -> Vec<Attribute<'a>> {
self.0.into_owned()
}
pub fn get<S>(&self, name: S) -> Option<&str>
where S: AsRef<str>
{
self.0.iter().find(|attr| attr.name == name.as_ref()).map(|a| a.value.as_ref())
}
pub fn set<N, V>(&mut self, name: N, value: V)
where N: Into<Cow<'a, str>>,
V: Into<Cow<'a, str>>
{
let (name, value) = (name.into(), value.into());
let attrs = self.0.to_mut();
if let Some(pos) = attrs.iter().position(|attr| attr.name == name) {
attrs[pos].value = value;
} else {
attrs.push(Attribute::new(name, value));
}
}
pub fn remove<S>(&mut self, name: S) -> Option<Attribute<'a>>
where S: AsRef<str>
{
let attrs = self.0.to_mut();
if let Some(pos) = attrs.iter().position(|attr| attr.name.as_ref() == name.as_ref()) {
Some(attrs.remove(pos))
} else {
None
}
}
pub fn iter<'b>(&'b self) -> Iter<'b, 'a> {
Iter {
inner: self.0.as_ref(),
index: 0,
}
}
}
pub struct Iter<'b, 'a: 'b> {
inner: &'b [Attribute<'a>],
index: usize,
}
impl<'a, 'b> Iterator for Iter<'b, 'a> {
type Item = &'b Attribute<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.index += 1;
self.inner.get(self.index - 1)
}
}
impl<'a, 'b> PartialEq<AttributeList<'b>> for AttributeList<'a> {
fn eq(&self, other: &AttributeList<'b>) -> bool {
let mut left = self.0.iter().collect::<Vec<_>>();
let mut right = other.0.iter().collect::<Vec<_>>();
left.sort();
right.sort();
left == right
}
}