1use crate::{
2 CursorSink, DeclarationValue, Kind, KindSet, NodeMetadata, NodeWithMetadata, Parse, Parser, Peek, Result,
3 SemanticEq, Span, State, T, ToCursors, ToSpan, token_macros,
4};
5use bumpalo::collections::Vec;
6
7use super::Declaration;
8
9#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize))]
23#[cfg_attr(feature = "serde", serde(bound(serialize = "D: serde::Serialize, R: serde::Serialize")))]
24pub struct Block<'a, D, R, M>
25where
26 D: DeclarationValue<'a, M>,
27 M: NodeMetadata,
28{
29 pub open_curly: token_macros::LeftCurly,
30 pub declarations: Vec<'a, Declaration<'a, D, M>>,
31 pub rules: Vec<'a, R>,
32 pub close_curly: Option<token_macros::RightCurly>,
33 #[cfg_attr(feature = "serde", serde(skip))]
34 pub meta: M,
35}
36
37impl<'a, D, R, M> NodeWithMetadata<M> for Block<'a, D, R, M>
38where
39 D: DeclarationValue<'a, M>,
40 M: NodeMetadata,
41{
42 fn metadata(&self) -> M {
43 self.meta
44 }
45}
46
47impl<'a, D, R, M> Peek<'a> for Block<'a, D, R, M>
48where
49 D: DeclarationValue<'a, M>,
50 M: NodeMetadata,
51{
52 const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::LeftCurly]);
53}
54
55impl<'a, D, R, M> Parse<'a> for Block<'a, D, R, M>
56where
57 D: DeclarationValue<'a, M>,
58 R: Parse<'a> + NodeWithMetadata<M>,
59 M: NodeMetadata,
60{
61 fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
62 where
63 Iter: Iterator<Item = crate::Cursor> + Clone,
64 {
65 let open_curly = p.parse::<T!['{']>()?;
66 let mut declarations = Vec::new_in(p.bump());
67 let mut rules = Vec::new_in(p.bump());
68 let mut meta = M::default();
69 loop {
70 if p.parse_if_peek::<T![' ']>()?.is_some() || p.parse_if_peek::<T![;]>()?.is_some() {
74 continue;
75 }
76 if p.at_end() {
77 break;
78 }
79 let c = p.peek_n(1);
80 if <T!['}']>::peek(p, c) {
81 break;
82 }
83 let old_state = p.set_state(State::Nested);
84 if <T![AtKeyword]>::peek(p, c) {
85 let rule = p.parse::<R>();
86 p.set_state(old_state);
87 let rule = rule?;
88 meta.merge(&rule.metadata());
89 rules.push(rule);
90 } else if let Ok(Some(decl)) = p.try_parse_if_peek::<Declaration<'a, D, M>>() {
91 p.set_state(old_state);
92 meta.merge(&decl.metadata());
93 declarations.push(decl);
94 } else {
95 let rule = p.parse::<R>();
96 p.set_state(old_state);
97 let rule = rule?;
98 meta.merge(&rule.metadata());
99 rules.push(rule);
100 }
101 }
102 let close_curly = p.parse_if_peek::<T!['}']>()?;
103 Ok(Self { open_curly, declarations, rules, close_curly, meta })
104 }
105}
106
107impl<'a, D, R, M> ToCursors for Block<'a, D, R, M>
108where
109 D: DeclarationValue<'a, M> + ToCursors,
110 R: ToCursors,
111 M: NodeMetadata,
112{
113 fn to_cursors(&self, s: &mut impl CursorSink) {
114 ToCursors::to_cursors(&self.open_curly, s);
115 ToCursors::to_cursors(&self.declarations, s);
116 ToCursors::to_cursors(&self.rules, s);
117 ToCursors::to_cursors(&self.close_curly, s);
118 }
119}
120
121impl<'a, D, R, M> ToSpan for Block<'a, D, R, M>
122where
123 D: DeclarationValue<'a, M> + ToSpan,
124 R: ToSpan,
125 M: NodeMetadata,
126{
127 fn to_span(&self) -> Span {
128 self.open_curly.to_span()
129 + if self.close_curly.is_some() {
130 self.close_curly.to_span()
131 } else {
132 self.declarations.to_span() + self.rules.to_span() + self.close_curly.to_span()
133 }
134 }
135}
136
137impl<'a, D, R, M> SemanticEq for Block<'a, D, R, M>
138where
139 D: DeclarationValue<'a, M>,
140 R: SemanticEq,
141 M: NodeMetadata,
142{
143 fn semantic_eq(&self, other: &Self) -> bool {
144 self.open_curly.semantic_eq(&other.open_curly)
145 && self.close_curly.semantic_eq(&other.close_curly)
146 && self.declarations.semantic_eq(&other.declarations)
147 && self.rules.semantic_eq(&other.rules)
148 }
149}
150
151#[cfg(test)]
152mod tests {
153 use super::*;
154 use crate::EmptyAtomSet;
155 use crate::{Cursor, test_helpers::*};
156
157 #[derive(Debug)]
158 struct Decl(T![Ident]);
159
160 impl<M: NodeMetadata> NodeWithMetadata<M> for Decl {
161 fn metadata(&self) -> M {
162 M::default()
163 }
164 }
165
166 impl<'a, M: NodeMetadata> DeclarationValue<'a, M> for Decl {
167 type ComputedValue = T![Eof];
168
169 fn is_initial(&self) -> bool {
170 false
171 }
172
173 fn is_inherit(&self) -> bool {
174 false
175 }
176
177 fn is_unset(&self) -> bool {
178 false
179 }
180
181 fn is_revert(&self) -> bool {
182 false
183 }
184
185 fn is_revert_layer(&self) -> bool {
186 false
187 }
188
189 fn needs_computing(&self) -> bool {
190 false
191 }
192
193 fn parse_specified_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _: Cursor) -> Result<Self>
194 where
195 Iter: Iterator<Item = crate::Cursor> + Clone,
196 {
197 p.parse::<T![Ident]>().map(Self)
198 }
199 }
200
201 impl ToCursors for Decl {
202 fn to_cursors(&self, s: &mut impl CursorSink) {
203 ToCursors::to_cursors(&self.0, s);
204 }
205 }
206
207 impl ToSpan for Decl {
208 fn to_span(&self) -> Span {
209 self.0.to_span()
210 }
211 }
212
213 impl SemanticEq for Decl {
214 fn semantic_eq(&self, other: &Self) -> bool {
215 self.0.semantic_eq(&other.0)
216 }
217 }
218
219 impl NodeWithMetadata<()> for T![Ident] {
220 fn metadata(&self) -> () {}
221 }
222
223 #[test]
224 fn size_test() {
225 assert_eq!(std::mem::size_of::<Block<Decl, T![Ident], ()>>(), 96);
226 }
227
228 #[test]
229 fn test_writes() {
230 assert_parse!(EmptyAtomSet::ATOMS, Block<Decl, T![Ident], ()>, "{color:black}");
231 }
232}