css_parse/syntax/
rule_list.rs1use super::prelude::*;
2use crate::token_macros;
3
4#[node]
21#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
22#[cfg_attr(
23 feature = "serde",
24 derive(serde::Serialize),
25 serde(bound(serialize = "R: serde::Serialize, M: serde::Serialize"))
26)]
27pub struct RuleList<'a, R, M>
28where
29 R: NodeWithMetadata<M>,
30 M: NodeMetadata,
31{
32 pub open_curly: token_macros::LeftCurly,
33 pub rules: Vec<'a, R>,
34 pub close_curly: Option<token_macros::RightCurly>,
35 #[cfg_attr(feature = "serde", serde(skip))]
36 pub meta: M,
37}
38
39impl<'a, R, M> Peek<'a> for RuleList<'a, R, M>
40where
41 R: NodeWithMetadata<M>,
42 M: NodeMetadata,
43{
44 const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::LeftCurly]);
45}
46
47impl<'a, R, M> Parse<'a> for RuleList<'a, R, M>
48where
49 R: Parse<'a> + NodeWithMetadata<M>,
50 M: NodeMetadata,
51{
52 fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
53 where
54 Iter: Iterator<Item = crate::Cursor> + Clone,
55 {
56 let nested = p.is(State::Nested);
57 let open_curly = p.parse::<T!['{']>()?;
58 let mut rules = Vec::new_in(p.alloc());
59 let mut meta = if nested { M::default().with_nested() } else { M::default() };
60 loop {
61 p.parse_if_peek::<T![;]>().ok();
62 if p.at_end() {
63 return Ok(Self { open_curly, rules, close_curly: None, meta });
64 }
65 let close_curly = p.parse_if_peek::<T!['}']>()?;
66 if close_curly.is_some() {
67 return Ok(Self { open_curly, rules, close_curly, meta });
68 }
69 let rule = p.parse::<R>()?;
70 meta = meta.merge(rule.metadata());
71 rules.push(rule);
72 }
73 }
74}
75
76impl<'a, R, M> ToCursors for RuleList<'a, R, M>
77where
78 R: ToCursors + NodeWithMetadata<M>,
79 M: NodeMetadata,
80{
81 fn to_cursors(&self, s: &mut impl CursorSink) {
82 ToCursors::to_cursors(&self.open_curly, s);
83 ToCursors::to_cursors(&self.rules, s);
84 ToCursors::to_cursors(&self.close_curly, s);
85 }
86}
87
88impl<'a, R, M> ToSpan for RuleList<'a, R, M>
89where
90 R: ToSpan + NodeWithMetadata<M>,
91 M: NodeMetadata,
92{
93 fn to_span(&self) -> css_lexer::Span {
94 self.open_curly.to_span()
95 + if let Some(close) = self.close_curly { close.to_span() } else { self.rules.to_span() }
96 }
97}
98
99impl<'a, R, M> NodeWithMetadata<M> for RuleList<'a, R, M>
100where
101 R: NodeWithMetadata<M>,
102 M: NodeMetadata,
103{
104 fn metadata(&self) -> M {
105 self.meta
106 }
107}
108
109impl<'a, R, M> SemanticEq for RuleList<'a, R, M>
110where
111 R: NodeWithMetadata<M> + SemanticEq,
112 M: NodeMetadata,
113{
114 fn semantic_eq(&self, other: &Self) -> bool {
115 self.open_curly.semantic_eq(&other.open_curly)
116 && self.rules.semantic_eq(&other.rules)
117 && self.close_curly.semantic_eq(&other.close_curly)
118 }
119}