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;
|
||||
|
||||
|
||||
@@ -457,9 +457,19 @@ impl StyleRule {
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StyleSheet {
|
||||
rules: Vec<StyleRule>,
|
||||
index: Option<StyleIndex>,
|
||||
}
|
||||
|
||||
impl Default for StyleSheet {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
rules: Vec::new(),
|
||||
index: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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>(
|
||||
&'a self,
|
||||
type_name: &str,
|
||||
@@ -563,6 +631,39 @@ fn split_selectors(input: &str) -> Vec<String> {
|
||||
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)]
|
||||
pub enum Overflow {
|
||||
#[default]
|
||||
|
||||
Reference in New Issue
Block a user