use std::fmt;
use std::str;
use std::mem;
use std::iter::{
Filter,
Map,
};
use std::slice::{
Iter,
IterMut,
};
use {
Attribute,
AttributeId,
AttributeNameRef,
AttributeValue,
WriteBuffer,
};
pub type SvgAttrFilter<'a> = Filter<Iter<'a, Attribute>, fn(&&Attribute) -> bool>;
pub type SvgAttrFilterMut<'a> = Filter<IterMut<'a, Attribute>, fn(&&mut Attribute) -> bool>;
pub struct Attributes(Vec<Attribute>);
impl Attributes {
#[inline]
pub fn new() -> Attributes {
Attributes(Vec::new())
}
#[inline]
pub fn get<'a, N>(&self, name: N) -> Option<&Attribute>
where AttributeNameRef<'a>: From<N>
{
let name = AttributeNameRef::from(name);
for v in &self.0 {
if v.name.into_ref() == name {
return Some(v);
}
}
None
}
#[inline]
pub fn get_mut<'a, N>(&mut self, name: N) -> Option<&mut Attribute>
where AttributeNameRef<'a>: From<N>
{
let name = AttributeNameRef::from(name);
for v in &mut self.0 {
if v.name.into_ref() == name {
return Some(v);
}
}
None
}
#[inline]
pub fn get_value<'a, N>(&self, name: N) -> Option<&AttributeValue>
where AttributeNameRef<'a>: From<N>
{
let name = AttributeNameRef::from(name);
for v in &self.0 {
if v.name.into_ref() == name {
return Some(&v.value);
}
}
None
}
#[inline]
pub fn get_value_mut<'a, N>(&mut self, name: N) -> Option<&mut AttributeValue>
where AttributeNameRef<'a>: From<N>
{
let name = AttributeNameRef::from(name);
for v in &mut self.0 {
if v.name.into_ref() == name {
return Some(&mut v.value);
}
}
None
}
pub fn insert(&mut self, attr: Attribute) {
if cfg!(debug_assertions) {
if attr.is_link() || attr.is_func_link() {
panic!("attribute with Link/FuncLink value must be set only via Node::set_attribute");
}
}
self.insert_impl(attr);
}
pub fn insert_from<'a, N, T>(&mut self, name: N, value: T)
where AttributeNameRef<'a>: From<N>, AttributeValue: From<T>
{
self.insert(Attribute::new(name, value));
}
pub fn insert_impl(&mut self, attr: Attribute) {
if self.0.capacity() == 0 {
self.0.reserve(16);
}
let idx = self.0.iter().position(|x| x.name == attr.name);
match idx {
Some(i) => { mem::replace(&mut self.0[i], attr); }
None => self.0.push(attr),
}
}
pub fn remove<'a, N>(&mut self, name: N)
where AttributeNameRef<'a>: From<N>, N: Copy
{
if cfg!(debug_assertions) {
let name = AttributeNameRef::from(name);
let attr = self.0.iter().find(|x| x.name.into_ref() == name);
if let Some(attr) = attr {
if attr.is_link() || attr.is_func_link() {
panic!("attribute with Link/FuncLink value must be remove \
only via Node::remove_attribute");
}
}
}
self.remove_impl(name);
}
pub fn remove_impl<'a, N>(&mut self, name: N)
where AttributeNameRef<'a>: From<N>
{
let name = AttributeNameRef::from(name);
let idx = self.0.iter().position(|x| x.name.into_ref() == name);
if let Some(i) = idx {
self.0.remove(i);
}
}
#[inline]
pub fn contains<'a, N>(&self, name: N) -> bool
where AttributeNameRef<'a>: From<N>
{
let name = AttributeNameRef::from(name);
self.0.iter().any(|a| a.name.into_ref() == name)
}
#[inline]
pub fn len(&self) -> usize {
self.0.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
pub fn iter(&self) -> Iter<Attribute> {
self.0.iter()
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<Attribute> {
self.0.iter_mut()
}
#[inline]
pub fn iter_svg<'a>(&'a self)
-> Map<SvgAttrFilter, fn(&'a Attribute) -> (AttributeId, &'a Attribute)>
{
fn map_svg(a: &Attribute) -> (AttributeId, &Attribute) { (a.id().unwrap(), a) }
self.filter_svg().map(map_svg)
}
#[inline]
pub fn iter_svg_mut<'a>(&'a mut self)
-> Map<SvgAttrFilterMut, fn(&'a mut Attribute) -> (AttributeId, &'a mut Attribute)>
{
fn map_svg(a: &mut Attribute) -> (AttributeId, &mut Attribute)
{ (a.id().unwrap(), a) }
self.filter_svg_mut().map(map_svg)
}
#[inline]
fn filter_svg(&self) -> SvgAttrFilter {
fn is_svg(a: &&Attribute) -> bool { a.is_svg() }
self.iter().filter(is_svg)
}
#[inline]
fn filter_svg_mut(&mut self) -> SvgAttrFilterMut {
fn is_svg(a: &&mut Attribute) -> bool { a.is_svg() }
self.iter_mut().filter(is_svg)
}
#[inline]
pub fn retain<F>(&mut self, mut f: F)
where F: FnMut(&Attribute) -> bool
{
if cfg!(debug_assertions) {
for attr in &self.0 {
if !f(attr) {
if attr.is_link() || attr.is_func_link() {
panic!("attribute with Link/FuncLink value must be remove \
only via Node::remove_attribute");
}
}
}
}
self.0.retain(f)
}
}
impl fmt::Debug for Attributes {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut out = Vec::with_capacity(256);
out.extend_from_slice(b"Attributes(");
for attr in self.iter() {
attr.write_buf(&mut out);
out.push(b',');
out.push(b' ');
}
out.pop();
out.pop();
out.push(b')');
write!(f, "{}", str::from_utf8(&out).unwrap())
}
}