1use crate::{
2 BadDeclaration, CursorSink, Declaration, DeclarationGroup, DeclarationOrBad, DeclarationValue, Kind, KindSet,
3 NodeMetadata, NodeWithMetadata, Parse, Parser, Peek, Result, RuleVariants, SemanticEq, Span, State, T, ToCursors,
4 ToSpan, token_macros,
5};
6use bumpalo::collections::Vec;
7
8#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize))]
22#[cfg_attr(feature = "serde", serde(bound(serialize = "D: serde::Serialize, R: serde::Serialize")))]
23pub struct Block<'a, D, R, M>
24where
25 D: DeclarationValue<'a, M>,
26 M: NodeMetadata,
27{
28 pub open_curly: token_macros::LeftCurly,
29 pub declarations: Vec<'a, Declaration<'a, D, M>>,
30 pub rules: Vec<'a, R>,
31 pub close_curly: Option<token_macros::RightCurly>,
32 #[cfg_attr(feature = "serde", serde(skip))]
33 pub meta: M,
34}
35
36impl<'a, D, R, M> NodeWithMetadata<M> for Block<'a, D, R, M>
37where
38 D: DeclarationValue<'a, M>,
39 M: NodeMetadata,
40{
41 fn metadata(&self) -> M {
42 self.meta
43 }
44}
45
46impl<'a, D, R, M> Peek<'a> for Block<'a, D, R, M>
47where
48 D: DeclarationValue<'a, M>,
49 M: NodeMetadata,
50{
51 const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::LeftCurly]);
52}
53
54impl<'a, D, R, M> Parse<'a> for Block<'a, D, R, M>
55where
56 D: DeclarationValue<'a, M>,
57 R: Parse<'a> + NodeWithMetadata<M> + RuleVariants<'a, DeclarationValue = D, Metadata = M>,
58 M: NodeMetadata,
59{
60 fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
61 where
62 Iter: Iterator<Item = crate::Cursor> + Clone,
63 {
64 let open_curly = p.parse::<T!['{']>()?;
65 let mut declarations = Vec::new_in(p.bump());
66 let mut rules = Vec::new_in(p.bump());
67 let mut meta = M::default();
68
69 let mut decls: Vec<'a, DeclarationOrBad<'a, D, M>> = Vec::new_in(p.bump());
72
73 macro_rules! flush_decls {
76 () => {
77 if !decls.is_empty() {
78 let group = DeclarationGroup { declarations: std::mem::replace(&mut decls, Vec::new_in(p.bump())) };
79 if let Some(rule) = R::from_declaration_group(group) {
80 meta = meta.merge(rule.metadata());
81 rules.push(rule);
82 }
83 }
84 };
85 }
86
87 loop {
88 p.consume_trivia_as_leading();
96 const ERROR_KINDS: KindSet = KindSet::new(&[
97 Kind::CdcOrCdo,
98 Kind::Semicolon,
99 Kind::RightParen,
100 Kind::RightSquare,
101 Kind::BadString,
102 Kind::BadUrl,
103 ]);
104 let c = p.peek_n(1);
105 if c == ERROR_KINDS {
106 let old_skip = p.set_skip(ERROR_KINDS);
107 p.consume_trivia_as_leading();
108 p.set_skip(old_skip);
109 continue;
110 }
111 if p.at_end() {
112 break;
113 }
114 let c = p.peek_n(1);
115 if <T!['}']>::peek(p, c) {
116 break;
117 }
118 let old_state = p.set_state(State::Nested);
119 let checkpoint = p.checkpoint();
120 if <T![AtKeyword]>::peek(p, c) {
121 flush_decls!();
123 let rule = p.parse::<R>();
124 p.set_state(old_state);
125 let rule = rule?;
126 meta = meta.merge(rule.metadata());
127 rules.push(rule);
128 } else if let Ok(Some(decl)) = p.try_parse_if_peek::<Declaration<'a, D, M>>() {
129 if decl.is_unknown() && !D::valid_declaration_name(p, decl.name.into()) {
146 p.rewind(checkpoint.clone());
147 if let Ok(rule) = p.parse::<R>()
148 && !rule.is_unknown()
149 {
150 flush_decls!();
152 p.set_state(old_state);
153 meta = meta.merge(rule.metadata());
154 rules.push(rule);
155 continue;
156 }
157 p.rewind(checkpoint);
159 p.parse::<Declaration<'a, D, M>>().ok();
160 }
161 p.set_state(old_state);
162 meta = meta.merge(decl.metadata());
163 declarations.push(decl);
164 } else {
165 let result = p.parse::<R>();
167 p.set_state(old_state);
168 match result {
169 Ok(rule) => {
170 flush_decls!();
171 meta = meta.merge(rule.metadata());
172 rules.push(rule);
173 }
174 Err(_) => {
175 p.rewind(checkpoint);
177 p.set_state(State::Nested);
178 if let Ok(bad_decl) = p.parse::<BadDeclaration>() {
179 p.set_state(old_state);
180 decls.push(DeclarationOrBad::Bad(bad_decl));
181 }
182 }
183 }
184 }
185 }
186
187 flush_decls!();
189 let close_curly = p.parse_if_peek::<T!['}']>()?;
190 Ok(Self { open_curly, declarations, rules, close_curly, meta })
191 }
192}
193
194impl<'a, D, R, M> ToCursors for Block<'a, D, R, M>
195where
196 D: DeclarationValue<'a, M> + ToCursors,
197 R: ToCursors,
198 M: NodeMetadata,
199{
200 fn to_cursors(&self, s: &mut impl CursorSink) {
201 ToCursors::to_cursors(&self.open_curly, s);
202 ToCursors::to_cursors(&self.declarations, s);
203 ToCursors::to_cursors(&self.rules, s);
204 ToCursors::to_cursors(&self.close_curly, s);
205 }
206}
207
208impl<'a, D, R, M> ToSpan for Block<'a, D, R, M>
209where
210 D: DeclarationValue<'a, M> + ToSpan,
211 R: ToSpan,
212 M: NodeMetadata,
213{
214 fn to_span(&self) -> Span {
215 self.open_curly.to_span()
216 + if self.close_curly.is_some() {
217 self.close_curly.to_span()
218 } else {
219 self.declarations.to_span() + self.rules.to_span() + self.close_curly.to_span()
220 }
221 }
222}
223
224impl<'a, D, R, M> SemanticEq for Block<'a, D, R, M>
225where
226 D: DeclarationValue<'a, M>,
227 R: SemanticEq,
228 M: NodeMetadata,
229{
230 fn semantic_eq(&self, other: &Self) -> bool {
231 self.open_curly.semantic_eq(&other.open_curly)
232 && self.close_curly.semantic_eq(&other.close_curly)
233 && self.declarations.semantic_eq(&other.declarations)
234 && self.rules.semantic_eq(&other.rules)
235 }
236}
237
238#[cfg(test)]
239mod tests {
240 use super::*;
241 use crate::EmptyAtomSet;
242 use crate::{Cursor, test_helpers::*};
243
244 #[derive(Debug)]
245 struct Decl(T![Ident]);
246
247 impl<M: NodeMetadata> NodeWithMetadata<M> for Decl {
248 fn metadata(&self) -> M {
249 M::default()
250 }
251 }
252
253 impl<'a, M: NodeMetadata> DeclarationValue<'a, M> for Decl {
254 type ComputedValue = T![Eof];
255
256 fn is_initial(&self) -> bool {
257 false
258 }
259
260 fn is_inherit(&self) -> bool {
261 false
262 }
263
264 fn is_unset(&self) -> bool {
265 false
266 }
267
268 fn is_revert(&self) -> bool {
269 false
270 }
271
272 fn is_revert_layer(&self) -> bool {
273 false
274 }
275
276 fn needs_computing(&self) -> bool {
277 false
278 }
279
280 fn parse_specified_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _: Cursor) -> Result<Self>
281 where
282 Iter: Iterator<Item = crate::Cursor> + Clone,
283 {
284 p.parse::<T![Ident]>().map(Self)
285 }
286 }
287
288 impl ToCursors for Decl {
289 fn to_cursors(&self, s: &mut impl CursorSink) {
290 ToCursors::to_cursors(&self.0, s);
291 }
292 }
293
294 impl ToSpan for Decl {
295 fn to_span(&self) -> Span {
296 self.0.to_span()
297 }
298 }
299
300 impl SemanticEq for Decl {
301 fn semantic_eq(&self, other: &Self) -> bool {
302 self.0.semantic_eq(&other.0)
303 }
304 }
305
306 impl NodeWithMetadata<()> for T![Ident] {
307 fn metadata(&self) {}
308 }
309
310 #[derive(Debug)]
311 struct Rule(T![Ident]);
312
313 impl<'a> Parse<'a> for Rule {
314 fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
315 where
316 I: Iterator<Item = Cursor> + Clone,
317 {
318 Ok(Self(p.parse::<T![Ident]>()?))
319 }
320 }
321
322 impl ToCursors for Rule {
323 fn to_cursors(&self, s: &mut impl CursorSink) {
324 ToCursors::to_cursors(&self.0, s);
325 }
326 }
327
328 impl ToSpan for Rule {
329 fn to_span(&self) -> Span {
330 self.0.to_span()
331 }
332 }
333
334 impl NodeWithMetadata<()> for Rule {
335 fn metadata(&self) {}
336 }
337
338 impl<'a> crate::RuleVariants<'a> for Rule {
339 type DeclarationValue = Decl;
340 type Metadata = ();
341 }
342
343 #[test]
344 fn size_test() {
345 assert_eq!(std::mem::size_of::<Block<Decl, Rule, ()>>(), 96);
346 }
347
348 #[test]
349 fn test_writes() {
350 assert_parse!(EmptyAtomSet::ATOMS, Block<Decl, Rule, ()>, "{color:black}");
351 }
352
353 #[test]
354 fn test_bad_string_in_block_does_not_hang() {
355 let bump = bumpalo::Bump::new();
356 for src in
357 [":{\".\n", "am:{\"\n", "alm:{\"\n", "alm:{\";.\n", "alm:{\"; }.\n", "alm:s {\n \x16\x00\x00:\";\n }\n"]
358 {
359 let lexer = css_lexer::Lexer::new(&EmptyAtomSet::ATOMS, src);
360 let mut parser = crate::Parser::new(&bump, src, lexer);
361 let _ = parser.parse::<Block<Decl, Rule, ()>>();
362 }
363 }
364}