#[derive(Debug, Clone)]
pub struct SelectorGroup {
pub selectors: Vec<Selector>,
}
#[derive(Debug, Clone)]
pub struct Selector {
pub compounds: Vec<CompoundEntry>,
}
#[derive(Debug, Clone)]
pub struct CompoundEntry {
pub combinator: Combinator,
pub compound: CompoundSelector,
}
#[derive(Debug, Clone, Default)]
pub struct CompoundSelector {
pub tag: Option<String>,
pub id: Option<String>,
pub classes: Vec<String>,
pub attrs: Vec<AttrSelector>,
pub pseudos: Vec<PseudoClass>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Combinator {
None,
Descendant,
Child,
NextSibling,
SubsequentSibling,
}
#[derive(Debug, Clone)]
pub struct AttrSelector {
pub name: String,
pub matcher: Option<AttrMatcher>,
}
#[derive(Debug, Clone)]
pub struct AttrMatcher {
pub op: AttrOp,
pub value: String,
pub case_insensitive: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AttrOp {
Exact,
Word,
DashPrefix,
Prefix,
Suffix,
Substring,
}
#[derive(Debug, Clone)]
pub enum PseudoClass {
FirstChild,
LastChild,
OnlyChild,
Empty,
Not(Box<CompoundSelector>),
NthChild(NthExpr),
NthLastChild(NthExpr),
}
#[derive(Debug, Clone, Copy)]
pub struct NthExpr {
pub a: i32,
pub b: i32,
}
impl NthExpr {
pub fn matches(&self, pos: i32) -> bool {
if self.a == 0 {
return pos == self.b;
}
let diff = pos - self.b;
diff % self.a == 0 && diff / self.a >= 0
}
}