1use crate::{
2 BangImportant, Cursor, CursorSink, DeclarationValue, Kind, KindSet, NodeMetadata, NodeWithMetadata, Parse, Parser,
3 Peek, Result, SemanticEq, Span, T, ToCursors, ToSpan, token_macros,
4};
5use std::marker::PhantomData;
6
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
31pub struct Declaration<'a, V, M>
32where
33 V: DeclarationValue<'a, M>,
34 M: NodeMetadata,
35{
36 pub name: token_macros::Ident,
37 pub colon: token_macros::Colon,
38 pub value: V,
39 pub important: Option<BangImportant>,
40 pub semicolon: Option<token_macros::Semicolon>,
41 #[cfg_attr(feature = "serde", serde(skip))]
42 _phantom: PhantomData<&'a M>,
43}
44
45impl<'a, V, M> Declaration<'a, V, M>
46where
47 V: DeclarationValue<'a, M>,
48 M: NodeMetadata,
49{
50 pub fn is_unknown(&self) -> bool {
51 self.value.is_unknown()
52 }
53}
54
55impl<'a, V, M> NodeWithMetadata<M> for Declaration<'a, V, M>
56where
57 V: DeclarationValue<'a, M>,
58 M: NodeMetadata,
59{
60 fn self_metadata(&self) -> M {
61 DeclarationValue::declaration_metadata(self)
64 }
65
66 fn metadata(&self) -> M {
67 DeclarationValue::declaration_metadata(self)
68 }
69}
70
71impl<'a, V, M> Peek<'a> for Declaration<'a, V, M>
72where
73 V: DeclarationValue<'a, M>,
74 M: NodeMetadata,
75{
76 const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::Ident]);
77
78 #[inline(always)]
79 fn peek<Iter>(p: &Parser<'a, Iter>, c: Cursor) -> bool
80 where
81 Iter: Iterator<Item = crate::Cursor> + Clone,
82 {
83 if c != Kind::Ident || p.peek_n(2) != Kind::Colon {
90 return false;
91 }
92
93 if c.token().is_dashed_ident() {
98 return true;
99 }
100
101 if p.peek_n(3) == Kind::Colon {
105 return false;
106 }
107
108 if p.peek_n(4) == Kind::LeftCurly || p.peek_n(5) == Kind::LeftCurly {
114 return false;
115 }
116
117 true
119 }
120}
121
122impl<'a, V, M> Parse<'a> for Declaration<'a, V, M>
123where
124 V: DeclarationValue<'a, M>,
125 M: NodeMetadata,
126{
127 fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
128 where
129 Iter: Iterator<Item = crate::Cursor> + Clone,
130 {
131 let name = p.parse::<T![Ident]>()?;
132 let colon = p.parse::<T![:]>()?;
133 let c: Cursor = name.into();
134 let value = <V>::parse_declaration_value(p, c)?;
135 let important = p.parse_if_peek::<BangImportant>()?;
136 let semicolon = p.parse_if_peek::<T![;]>()?;
137 Ok(Self { name, colon, value, important, semicolon, _phantom: PhantomData })
138 }
139}
140
141impl<'a, V, M> ToCursors for Declaration<'a, V, M>
142where
143 V: DeclarationValue<'a, M> + ToCursors,
144 M: NodeMetadata,
145{
146 fn to_cursors(&self, s: &mut impl CursorSink) {
147 ToCursors::to_cursors(&self.name, s);
148 ToCursors::to_cursors(&self.colon, s);
149 ToCursors::to_cursors(&self.value, s);
150 ToCursors::to_cursors(&self.important, s);
151 ToCursors::to_cursors(&self.semicolon, s);
152 }
153}
154
155impl<'a, V, M> ToSpan for Declaration<'a, V, M>
156where
157 V: DeclarationValue<'a, M> + ToSpan,
158 M: NodeMetadata,
159{
160 fn to_span(&self) -> Span {
161 self.name.to_span() + self.value.to_span() + self.important.to_span() + self.semicolon.to_span()
162 }
163}
164
165impl<'a, V, M> SemanticEq for Declaration<'a, V, M>
166where
167 V: DeclarationValue<'a, M>,
168 M: NodeMetadata,
169{
170 fn semantic_eq(&self, other: &Self) -> bool {
171 self.name.semantic_eq(&other.name)
173 && self.value.semantic_eq(&other.value)
174 && self.important.semantic_eq(&other.important)
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181 use crate::EmptyAtomSet;
182 use crate::SemanticEq;
183 use crate::test_helpers::*;
184
185 #[derive(Debug)]
186 struct Decl(T![Ident]);
187
188 impl<M: NodeMetadata> NodeWithMetadata<M> for Decl {
189 fn metadata(&self) -> M {
190 M::default()
191 }
192 }
193
194 impl<'a, M: NodeMetadata> DeclarationValue<'a, M> for Decl {
195 type ComputedValue = T![Eof];
196
197 fn is_initial(&self) -> bool {
198 false
199 }
200
201 fn is_inherit(&self) -> bool {
202 false
203 }
204
205 fn is_unset(&self) -> bool {
206 false
207 }
208
209 fn is_revert(&self) -> bool {
210 false
211 }
212
213 fn is_revert_layer(&self) -> bool {
214 false
215 }
216
217 fn needs_computing(&self) -> bool {
218 false
219 }
220
221 fn parse_specified_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _name: Cursor) -> Result<Self>
222 where
223 Iter: Iterator<Item = crate::Cursor> + Clone,
224 {
225 p.parse::<T![Ident]>().map(Self)
226 }
227 }
228
229 impl ToCursors for Decl {
230 fn to_cursors(&self, s: &mut impl CursorSink) {
231 s.append(self.0.into())
232 }
233 }
234
235 impl ToSpan for Decl {
236 fn to_span(&self) -> Span {
237 self.0.to_span()
238 }
239 }
240
241 impl SemanticEq for Decl {
242 fn semantic_eq(&self, other: &Self) -> bool {
243 self.0.semantic_eq(&other.0)
244 }
245 }
246
247 #[test]
248 fn size_test() {
249 assert_eq!(std::mem::size_of::<Declaration<Decl, ()>>(), 80);
250 }
251
252 #[test]
253 fn test_writes() {
254 assert_parse!(EmptyAtomSet::ATOMS, Declaration<Decl, ()>, "color:black;");
255 }
256}