selectors/
nth_index_cache.rs1use std::hash::Hash;
6
7use crate::{parser::Selector, tree::OpaqueElement, SelectorImpl};
8use fxhash::FxHashMap;
9
10#[derive(Default)]
16pub struct NthIndexCache {
17 nth: NthIndexCacheInner,
18 nth_of_selectors: NthIndexOfSelectorsCaches,
19 nth_last: NthIndexCacheInner,
20 nth_last_of_selectors: NthIndexOfSelectorsCaches,
21 nth_of_type: NthIndexCacheInner,
22 nth_last_of_type: NthIndexCacheInner,
23}
24
25impl NthIndexCache {
26 pub fn get<Impl: SelectorImpl>(
28 &mut self,
29 is_of_type: bool,
30 is_from_end: bool,
31 selectors: &[Selector<Impl>],
32 ) -> &mut NthIndexCacheInner {
33 if is_of_type {
34 return if is_from_end {
35 &mut self.nth_last_of_type
36 } else {
37 &mut self.nth_of_type
38 };
39 }
40 if !selectors.is_empty() {
41 return if is_from_end {
42 self.nth_last_of_selectors.lookup(selectors)
43 } else {
44 self.nth_of_selectors.lookup(selectors)
45 };
46 }
47 if is_from_end {
48 &mut self.nth_last
49 } else {
50 &mut self.nth
51 }
52 }
53}
54
55#[derive(Hash, Eq, PartialEq)]
56struct SelectorListCacheKey(usize);
57
58impl SelectorListCacheKey {
60 fn new<Impl: SelectorImpl>(selectors: &[Selector<Impl>]) -> Self {
62 Self(selectors.as_ptr() as usize)
63 }
64}
65
66#[derive(Default)]
68pub struct NthIndexOfSelectorsCaches(FxHashMap<SelectorListCacheKey, NthIndexCacheInner>);
69
70impl NthIndexOfSelectorsCaches {
73 pub fn lookup<Impl: SelectorImpl>(
74 &mut self,
75 selectors: &[Selector<Impl>],
76 ) -> &mut NthIndexCacheInner {
77 self.0
78 .entry(SelectorListCacheKey::new(selectors))
79 .or_default()
80 }
81}
82
83#[derive(Default)]
85pub struct NthIndexCacheInner(FxHashMap<OpaqueElement, i32>);
86
87impl NthIndexCacheInner {
88 pub fn lookup(&mut self, el: OpaqueElement) -> Option<i32> {
90 self.0.get(&el).copied()
91 }
92
93 pub fn insert(&mut self, element: OpaqueElement, index: i32) {
95 self.0.insert(element, index);
96 }
97
98 pub fn is_empty(&self) -> bool {
100 self.0.is_empty()
101 }
102}