style/stylesheets/
rule_list.rs1use crate::shared_lock::{DeepCloneWithLock, Locked};
8use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
9use crate::str::CssStringWriter;
10use crate::stylesheets::loader::StylesheetLoader;
11use crate::stylesheets::rule_parser::InsertRuleContext;
12use crate::stylesheets::stylesheet::StylesheetContents;
13use crate::stylesheets::{AllowImportRules, CssRule, CssRuleTypes, RulesMutateError};
14#[cfg(feature = "gecko")]
15use malloc_size_of::{MallocShallowSizeOf, MallocSizeOfOps};
16use servo_arc::Arc;
17use std::fmt::{self, Write};
18
19use super::CssRuleType;
20
21#[derive(Debug, ToShmem)]
23pub struct CssRules(pub Vec<CssRule>);
24
25impl CssRules {
26 pub fn is_empty(&self) -> bool {
28 self.0.is_empty()
29 }
30}
31
32impl DeepCloneWithLock for CssRules {
33 fn deep_clone_with_lock(&self, lock: &SharedRwLock, guard: &SharedRwLockReadGuard) -> Self {
34 CssRules(
35 self.0
36 .iter()
37 .map(|x| x.deep_clone_with_lock(lock, guard))
38 .collect(),
39 )
40 }
41}
42
43impl CssRules {
44 #[cfg(feature = "gecko")]
46 pub fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize {
47 let mut n = self.0.shallow_size_of(ops);
48 for rule in self.0.iter() {
49 n += rule.size_of(guard, ops);
50 }
51 n
52 }
53
54 pub fn new(rules: Vec<CssRule>, shared_lock: &SharedRwLock) -> Arc<Locked<CssRules>> {
56 Arc::new(shared_lock.wrap(CssRules(rules)))
57 }
58
59 fn only_ns_or_import(&self) -> bool {
62 self.0.iter().all(|r| match *r {
63 CssRule::Namespace(..) | CssRule::Import(..) => true,
64 _ => false,
65 })
66 }
67
68 pub fn remove_rule(&mut self, index: usize) -> Result<(), RulesMutateError> {
70 if index >= self.0.len() {
72 return Err(RulesMutateError::IndexSize);
73 }
74
75 {
76 let ref rule = self.0[index];
78
79 if let CssRule::Namespace(..) = *rule {
81 if !self.only_ns_or_import() {
82 return Err(RulesMutateError::InvalidState);
83 }
84 }
85 }
86
87 self.0.remove(index);
89 Ok(())
90 }
91
92 pub fn to_css_block(
97 &self,
98 guard: &SharedRwLockReadGuard,
99 dest: &mut CssStringWriter,
100 ) -> fmt::Result {
101 dest.write_str(" {")?;
102 self.to_css_block_without_opening(guard, dest)
103 }
104
105 pub fn to_css_block_without_opening(
107 &self,
108 guard: &SharedRwLockReadGuard,
109 dest: &mut CssStringWriter,
110 ) -> fmt::Result {
111 for rule in self.0.iter() {
112 if rule.is_empty_nested_declarations(guard) {
113 continue;
114 }
115
116 dest.write_str("\n ")?;
117 let old_len = dest.len();
118 rule.to_css(guard, dest)?;
119 debug_assert_ne!(old_len, dest.len());
120 }
121 dest.write_str("\n}")
122 }
123}
124
125pub trait CssRulesHelpers {
127 fn insert_rule(
136 &self,
137 lock: &SharedRwLock,
138 rule: &str,
139 parent_stylesheet_contents: &StylesheetContents,
140 index: usize,
141 nested: CssRuleTypes,
142 parse_relative_rule_type: Option<CssRuleType>,
143 loader: Option<&dyn StylesheetLoader>,
144 allow_import_rules: AllowImportRules,
145 ) -> Result<CssRule, RulesMutateError>;
146}
147
148impl CssRulesHelpers for Locked<CssRules> {
149 fn insert_rule(
150 &self,
151 lock: &SharedRwLock,
152 rule: &str,
153 parent_stylesheet_contents: &StylesheetContents,
154 index: usize,
155 containing_rule_types: CssRuleTypes,
156 parse_relative_rule_type: Option<CssRuleType>,
157 loader: Option<&dyn StylesheetLoader>,
158 allow_import_rules: AllowImportRules,
159 ) -> Result<CssRule, RulesMutateError> {
160 let new_rule = {
161 let read_guard = lock.read();
162 let rules = self.read_with(&read_guard);
163
164 if index > rules.0.len() {
166 return Err(RulesMutateError::IndexSize);
167 }
168
169 let insert_rule_context = InsertRuleContext {
170 rule_list: &rules.0,
171 index,
172 containing_rule_types,
173 parse_relative_rule_type,
174 };
175
176 CssRule::parse(
178 &rule,
179 insert_rule_context,
180 parent_stylesheet_contents,
181 lock,
182 loader,
183 allow_import_rules,
184 )?
185 };
186
187 {
188 let mut write_guard = lock.write();
189 let rules = self.write_with(&mut write_guard);
190 rules.0.insert(index, new_rule.clone());
191 }
192
193 Ok(new_rule)
194 }
195}