use matching::ElementFlags;
use parser::{AttrSelector, SelectorImpl};
use std::ascii::AsciiExt;
pub static SELECTOR_WHITESPACE: &'static [char] = &[' ', '\t', '\n', '\r', '\x0C'];
pub trait MatchAttr {
type Impl: SelectorImpl;
fn match_attr_has(
&self,
attr: &AttrSelector<Self::Impl>) -> bool;
fn match_attr_equals(
&self,
attr: &AttrSelector<Self::Impl>,
value: &<Self::Impl as SelectorImpl>::AttrValue) -> bool;
fn match_attr_equals_ignore_ascii_case(
&self,
attr: &AttrSelector<Self::Impl>,
value: &<Self::Impl as SelectorImpl>::AttrValue) -> bool;
fn match_attr_includes(
&self,
attr: &AttrSelector<Self::Impl>,
value: &<Self::Impl as SelectorImpl>::AttrValue) -> bool;
fn match_attr_dash(
&self,
attr: &AttrSelector<Self::Impl>,
value: &<Self::Impl as SelectorImpl>::AttrValue) -> bool;
fn match_attr_prefix(
&self,
attr: &AttrSelector<Self::Impl>,
value: &<Self::Impl as SelectorImpl>::AttrValue) -> bool;
fn match_attr_substring(
&self,
attr: &AttrSelector<Self::Impl>,
value: &<Self::Impl as SelectorImpl>::AttrValue) -> bool;
fn match_attr_suffix(
&self,
attr: &AttrSelector<Self::Impl>,
value: &<Self::Impl as SelectorImpl>::AttrValue) -> bool;
}
pub trait MatchAttrGeneric {
type Impl: SelectorImpl;
fn match_attr<F>(&self, attr: &AttrSelector<Self::Impl>, test: F) -> bool where F: Fn(&str) -> bool;
}
impl<T> MatchAttr for T where T: MatchAttrGeneric, T::Impl: SelectorImpl<AttrValue = String> {
type Impl = T::Impl;
fn match_attr_has(&self, attr: &AttrSelector<Self::Impl>) -> bool {
self.match_attr(attr, |_| true)
}
fn match_attr_equals(&self, attr: &AttrSelector<Self::Impl>, value: &String) -> bool {
self.match_attr(attr, |v| v == value)
}
fn match_attr_equals_ignore_ascii_case(&self, attr: &AttrSelector<Self::Impl>,
value: &String) -> bool {
self.match_attr(attr, |v| v.eq_ignore_ascii_case(value))
}
fn match_attr_includes(&self, attr: &AttrSelector<Self::Impl>, value: &String) -> bool {
self.match_attr(attr, |attr_value| {
attr_value.split(SELECTOR_WHITESPACE).any(|v| v == value)
})
}
fn match_attr_dash(&self, attr: &AttrSelector<Self::Impl>, value: &String) -> bool {
self.match_attr(attr, |attr_value| {
if !attr_value.starts_with(value) {
return false
}
if attr_value.len() == value.len() {
return true
}
attr_value.as_bytes()[value.len()] == '-' as u8
})
}
fn match_attr_prefix(&self, attr: &AttrSelector<Self::Impl>, value: &String) -> bool {
self.match_attr(attr, |attr_value| {
attr_value.starts_with(value)
})
}
fn match_attr_substring(&self, attr: &AttrSelector<Self::Impl>, value: &String) -> bool {
self.match_attr(attr, |attr_value| {
attr_value.contains(value)
})
}
fn match_attr_suffix(&self, attr: &AttrSelector<Self::Impl>, value: &String) -> bool {
self.match_attr(attr, |attr_value| {
attr_value.ends_with(value)
})
}
}
pub trait Element: MatchAttr + Sized {
fn parent_element(&self) -> Option<Self>;
fn first_child_element(&self) -> Option<Self>;
fn last_child_element(&self) -> Option<Self>;
fn prev_sibling_element(&self) -> Option<Self>;
fn next_sibling_element(&self) -> Option<Self>;
fn is_html_element_in_html_document(&self) -> bool;
fn get_local_name(&self) -> &<Self::Impl as SelectorImpl>::BorrowedLocalName;
fn get_namespace(&self) -> &<Self::Impl as SelectorImpl>::BorrowedNamespaceUrl;
fn match_non_ts_pseudo_class(&self, pc: <Self::Impl as SelectorImpl>::NonTSPseudoClass) -> bool;
fn get_id(&self) -> Option<<Self::Impl as SelectorImpl>::Identifier>;
fn has_class(&self, name: &<Self::Impl as SelectorImpl>::ClassName) -> bool;
fn is_empty(&self) -> bool;
fn is_root(&self) -> bool;
fn each_class<F>(&self, callback: F) where F: FnMut(&<Self::Impl as SelectorImpl>::ClassName);
fn insert_flags(&self, _flags: ElementFlags) {}
}