1use crate::{
2 BangImportant, Cursor, CursorSink, DeclarationValue, Kind, NodeMetadata, NodeWithMetadata, Parse, Parser, Peek,
3 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> NodeWithMetadata<M> for Declaration<'a, V, M>
46where
47 V: DeclarationValue<'a, M>,
48 M: NodeMetadata,
49{
50 fn metadata(&self) -> M {
51 DeclarationValue::declaration_metadata(self)
52 }
53}
54
55impl<'a, V, M> Peek<'a> for Declaration<'a, V, M>
56where
57 V: DeclarationValue<'a, M>,
58 M: NodeMetadata,
59{
60 fn peek<Iter>(p: &Parser<'a, Iter>, c: Cursor) -> bool
61 where
62 Iter: Iterator<Item = crate::Cursor> + Clone,
63 {
64 c == Kind::Ident && p.peek_n(2) == Kind::Colon
65 }
66}
67
68impl<'a, V, M> Parse<'a> for Declaration<'a, V, M>
69where
70 V: DeclarationValue<'a, M>,
71 M: NodeMetadata,
72{
73 fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
74 where
75 Iter: Iterator<Item = crate::Cursor> + Clone,
76 {
77 let name = p.parse::<T![Ident]>()?;
78 let colon = p.parse::<T![:]>()?;
79 let c: Cursor = name.into();
80 let value = <V>::parse_declaration_value(p, c)?;
81 let important = p.parse_if_peek::<BangImportant>()?;
82 let semicolon = p.parse_if_peek::<T![;]>()?;
83 Ok(Self { name, colon, value, important, semicolon, _phantom: PhantomData })
84 }
85}
86
87impl<'a, V, M> ToCursors for Declaration<'a, V, M>
88where
89 V: DeclarationValue<'a, M> + ToCursors,
90 M: NodeMetadata,
91{
92 fn to_cursors(&self, s: &mut impl CursorSink) {
93 ToCursors::to_cursors(&self.name, s);
94 ToCursors::to_cursors(&self.colon, s);
95 ToCursors::to_cursors(&self.value, s);
96 ToCursors::to_cursors(&self.important, s);
97 ToCursors::to_cursors(&self.semicolon, s);
98 }
99}
100
101impl<'a, V, M> ToSpan for Declaration<'a, V, M>
102where
103 V: DeclarationValue<'a, M> + ToSpan,
104 M: NodeMetadata,
105{
106 fn to_span(&self) -> Span {
107 self.name.to_span() + self.value.to_span() + self.important.to_span() + self.semicolon.to_span()
108 }
109}
110
111impl<'a, V, M> SemanticEq for Declaration<'a, V, M>
112where
113 V: DeclarationValue<'a, M>,
114 M: NodeMetadata,
115{
116 fn semantic_eq(&self, other: &Self) -> bool {
117 self.name.semantic_eq(&other.name)
119 && self.value.semantic_eq(&other.value)
120 && self.important.semantic_eq(&other.important)
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127 use crate::EmptyAtomSet;
128 use crate::SemanticEq;
129 use crate::test_helpers::*;
130
131 #[derive(Debug)]
132 struct Decl(T![Ident]);
133
134 impl<M: NodeMetadata> NodeWithMetadata<M> for Decl {
135 fn metadata(&self) -> M {
136 M::default()
137 }
138 }
139
140 impl<'a, M: NodeMetadata> DeclarationValue<'a, M> for Decl {
141 type ComputedValue = T![Eof];
142
143 fn is_initial(&self) -> bool {
144 false
145 }
146
147 fn is_inherit(&self) -> bool {
148 false
149 }
150
151 fn is_unset(&self) -> bool {
152 false
153 }
154
155 fn is_revert(&self) -> bool {
156 false
157 }
158
159 fn is_revert_layer(&self) -> bool {
160 false
161 }
162
163 fn needs_computing(&self) -> bool {
164 false
165 }
166
167 fn parse_specified_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _name: Cursor) -> Result<Self>
168 where
169 Iter: Iterator<Item = crate::Cursor> + Clone,
170 {
171 p.parse::<T![Ident]>().map(Self)
172 }
173 }
174
175 impl ToCursors for Decl {
176 fn to_cursors(&self, s: &mut impl CursorSink) {
177 s.append(self.0.into())
178 }
179 }
180
181 impl ToSpan for Decl {
182 fn to_span(&self) -> Span {
183 self.0.to_span()
184 }
185 }
186
187 impl SemanticEq for Decl {
188 fn semantic_eq(&self, other: &Self) -> bool {
189 self.0.semantic_eq(&other.0)
190 }
191 }
192
193 #[test]
194 fn size_test() {
195 assert_eq!(std::mem::size_of::<Declaration<Decl, ()>>(), 80);
196 }
197
198 #[test]
199 fn test_writes() {
200 assert_parse!(EmptyAtomSet::ATOMS, Declaration<Decl, ()>, "color:black;");
201 }
202}