css_parse/syntax/
rule_list.rs1use crate::{Cursor, CursorSink, Parse, Parser, Peek, Result, T, ToCursors, ToSpan, token_macros};
2use bumpalo::collections::Vec;
3
4#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(tag = "type"))]
22pub struct RuleList<'a, R> {
23 pub open_curly: token_macros::LeftCurly,
24 pub rules: Vec<'a, R>,
25 pub close_curly: Option<token_macros::RightCurly>,
26}
27
28impl<'a, R> Peek<'a> for RuleList<'a, R> {
29 fn peek(p: &Parser<'a>, c: Cursor) -> bool {
30 <token_macros::LeftCurly>::peek(p, c)
31 }
32}
33
34impl<'a, R: Parse<'a>> Parse<'a> for RuleList<'a, R> {
35 fn parse(p: &mut Parser<'a>) -> Result<Self> {
36 let open_curly = p.parse::<T!['{']>()?;
37 let mut rules = Vec::new_in(p.bump());
38 loop {
39 p.parse_if_peek::<T![;]>().ok();
40 if p.at_end() {
41 return Ok(Self { open_curly, rules, close_curly: None });
42 }
43 let close_curly = p.parse_if_peek::<T!['}']>()?;
44 if close_curly.is_some() {
45 return Ok(Self { open_curly, rules, close_curly });
46 }
47 rules.push(p.parse::<R>()?);
48 }
49 }
50}
51
52impl<'a, R: ToCursors> ToCursors for RuleList<'a, R> {
53 fn to_cursors(&self, s: &mut impl CursorSink) {
54 ToCursors::to_cursors(&self.open_curly, s);
55 ToCursors::to_cursors(&self.rules, s);
56 ToCursors::to_cursors(&self.close_curly, s);
57 }
58}
59
60impl<'a, R: ToSpan> ToSpan for RuleList<'a, R> {
61 fn to_span(&self) -> css_lexer::Span {
62 self.open_curly.to_span()
63 + if let Some(close) = self.close_curly { close.to_span() } else { self.rules.to_span() }
64 }
65}