lewp_css/domain/
css_rules.rs1use {
5 super::{
6 at_rules::VendorPrefixedAtRule,
7 CssRule::{self},
8 HasCssRules,
9 RulesMutateError::{self},
10 },
11 cssparser::ToCss,
12 std::fmt,
13};
14
15#[derive(Default, Debug, Clone)]
17pub struct CssRules(pub Vec<CssRule>);
18
19impl ToCss for CssRules {
20 fn to_css<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
21 for cssRule in self.0.iter() {
22 cssRule.to_css(dest)?;
23 }
24
25 Ok(())
26 }
27}
28
29impl HasCssRules for CssRules {
30 #[inline(always)]
31 fn css_rules(&self) -> &CssRules {
32 self
33 }
34
35 #[inline(always)]
36 fn css_rules_mut(&mut self) -> &mut CssRules {
37 self
38 }
39
40 #[inline(always)]
41 fn css_rules_slice(&self) -> &[CssRule] {
42 &self.0[..]
43 }
44
45 #[inline(always)]
46 fn css_rules_vec(&self) -> &Vec<CssRule> {
47 &self.0
48 }
49
50 #[inline(always)]
51 fn css_rules_vec_mut(&mut self) -> &mut Vec<CssRule> {
52 &mut self.0
53 }
54}
55
56impl CssRules {
57 #[inline(always)]
59 pub fn vendor_prefix_at_rules<
60 AtRule: VendorPrefixedAtRule,
61 CssRuleMatcher: Fn(&CssRule) -> Option<&AtRule>,
62 VendorPrefixer: Fn(usize, &AtRule) -> Vec<CssRule>,
63 >(
64 &mut self,
65 remove_unprefixed_at_rule: bool,
66 css_rule_matcher: CssRuleMatcher,
67 vendor_prefixer: VendorPrefixer,
68 ) {
69 let mut index = 0;
70 while index < self.0.len() {
71 let newCssRulesToInsert = match css_rule_matcher(unsafe {
72 self.0.get_unchecked(index)
73 }) {
74 None => None,
75 Some(atRule) => {
76 if atRule.isNotVendorPrefixed() {
77 Some(vendor_prefixer(index, atRule))
78 } else {
79 None
80 }
81 }
82 };
83
84 index += if let Some(mut newCssRulesToInsert) = newCssRulesToInsert
85 {
86 let indexIncrement = newCssRulesToInsert.len();
87
88 for newCssRuleToInsert in newCssRulesToInsert.drain(..) {
90 self.css_rules_vec_mut().insert(index, newCssRuleToInsert);
91 }
92 if remove_unprefixed_at_rule {
93 self.css_rules_vec_mut().remove(index + indexIncrement);
94 indexIncrement
95 } else {
96 indexIncrement + 1
97 }
98 } else {
99 1
100 };
101 }
102 }
103
104 pub fn is_empty(&self) -> bool {
106 self.0.is_empty()
107 }
108
109 fn only_namespace_or_import(&self) -> bool {
111 use self::CssRule::*;
112
113 self.0.iter().all(|r| match *r {
114 Namespace(..) | Import(..) => true,
115 _ => false,
116 })
117 }
118
119 pub fn remove_rule(
121 &mut self,
122 index: usize,
123 ) -> Result<(), RulesMutateError> {
124 use self::{CssRule::Namespace, RulesMutateError::*};
125
126 if index >= self.0.len() {
128 return Err(IndexSize);
129 }
130
131 {
132 let rule = &self.0[index];
134
135 if let Namespace(..) = *rule {
137 if !self.only_namespace_or_import() {
138 return Err(InvalidState);
139 }
140 }
141 }
142
143 self.0.remove(index);
145
146 Ok(())
147 }
148}