Phase 4.1: Add StyleIndex struct and build_index() to StyleSheet
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
|
||||||
@@ -457,9 +457,19 @@ impl StyleRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct StyleSheet {
|
pub struct StyleSheet {
|
||||||
rules: Vec<StyleRule>,
|
rules: Vec<StyleRule>,
|
||||||
|
index: Option<StyleIndex>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for StyleSheet {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
rules: Vec::new(),
|
||||||
|
index: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StyleSheet {
|
impl StyleSheet {
|
||||||
@@ -473,6 +483,64 @@ impl StyleSheet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn build_index(&mut self) {
|
||||||
|
let mut index = StyleIndex::new();
|
||||||
|
index.epoch += 1;
|
||||||
|
|
||||||
|
for (i, rule) in self.rules.iter().enumerate() {
|
||||||
|
let specificity = rule.selector.specificity();
|
||||||
|
index.rule_specificities.push(specificity);
|
||||||
|
index.rules.push(rule.clone());
|
||||||
|
|
||||||
|
if rule.selector.compounds.len() == 1 {
|
||||||
|
if let Some(compound) = rule.selector.compounds.first() {
|
||||||
|
let tag_key = compound.tag.as_deref().unwrap_or("*");
|
||||||
|
index.by_tag.entry(tag_key.to_string()).or_default().push(i);
|
||||||
|
|
||||||
|
if tag_key == "*" {
|
||||||
|
index.universal_rules.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for cls in &compound.classes {
|
||||||
|
index.by_class.entry(cls.clone()).or_default().push(i);
|
||||||
|
index.by_tag_class.entry((tag_key.to_string(), cls.clone())).or_default().push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(id) = &compound.id {
|
||||||
|
index.by_id.entry(id.clone()).or_default().push(i);
|
||||||
|
index.by_tag_id.entry((tag_key.to_string(), id.clone())).or_default().push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Some(compound) = rule.selector.compounds.last() {
|
||||||
|
let tag_key = compound.tag.as_deref().unwrap_or("*");
|
||||||
|
index.by_tag.entry(tag_key.to_string()).or_default().push(i);
|
||||||
|
|
||||||
|
if tag_key == "*" {
|
||||||
|
index.universal_rules.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for cls in &compound.classes {
|
||||||
|
index.by_class.entry(cls.clone()).or_default().push(i);
|
||||||
|
index.by_tag_class.entry((tag_key.to_string(), cls.clone())).or_default().push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(id) = &compound.id {
|
||||||
|
index.by_id.entry(id.clone()).or_default().push(i);
|
||||||
|
index.by_tag_id.entry((tag_key.to_string(), id.clone())).or_default().push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index.complex_rules.push((i, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.index = Some(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_index(&self) -> bool {
|
||||||
|
self.index.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn matching_rules<'a>(
|
pub fn matching_rules<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
type_name: &str,
|
type_name: &str,
|
||||||
@@ -563,6 +631,39 @@ fn split_selectors(input: &str) -> Vec<String> {
|
|||||||
parts
|
parts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type RuleId = usize;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct StyleIndex {
|
||||||
|
pub by_tag: HashMap<String, Vec<RuleId>>,
|
||||||
|
pub by_class: HashMap<String, Vec<RuleId>>,
|
||||||
|
pub by_id: HashMap<String, Vec<RuleId>>,
|
||||||
|
pub by_tag_class: HashMap<(String, String), Vec<RuleId>>,
|
||||||
|
pub by_tag_id: HashMap<(String, String), Vec<RuleId>>,
|
||||||
|
pub complex_rules: Vec<(RuleId, RuleId)>,
|
||||||
|
pub universal_rules: Vec<RuleId>,
|
||||||
|
pub rule_specificities: Vec<(u32, u32, u32)>,
|
||||||
|
pub rules: Vec<StyleRule>,
|
||||||
|
pub epoch: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StyleIndex {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
by_tag: HashMap::new(),
|
||||||
|
by_class: HashMap::new(),
|
||||||
|
by_id: HashMap::new(),
|
||||||
|
by_tag_class: HashMap::new(),
|
||||||
|
by_tag_id: HashMap::new(),
|
||||||
|
complex_rules: Vec::new(),
|
||||||
|
universal_rules: Vec::new(),
|
||||||
|
rule_specificities: Vec::new(),
|
||||||
|
rules: Vec::new(),
|
||||||
|
epoch: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
pub enum Overflow {
|
pub enum Overflow {
|
||||||
#[default]
|
#[default]
|
||||||
|
|||||||
Reference in New Issue
Block a user