css_parse/syntax/
declaration.rs1use crate::{
2 BangImportant, Cursor, CursorSink, DeclarationValue, Kind, Parse, Parser, Peek, Result, Span, T, ToCursors, ToSpan,
3 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(tag = "type"))]
31pub struct Declaration<'a, V: DeclarationValue<'a>> {
32 pub name: token_macros::Ident,
33 pub colon: token_macros::Colon,
34 pub value: V,
35 pub important: Option<BangImportant>,
36 pub semicolon: Option<token_macros::Semicolon>,
37 #[cfg_attr(feature = "serde", serde(skip))]
38 _phantom: PhantomData<&'a ()>,
39}
40
41impl<'a, V: DeclarationValue<'a>> Peek<'a> for Declaration<'a, V> {
42 fn peek(p: &Parser<'a>, c: Cursor) -> bool {
43 c == Kind::Ident && p.peek_n(2) == Kind::Colon
44 }
45}
46
47impl<'a, V: DeclarationValue<'a>> Parse<'a> for Declaration<'a, V> {
48 fn parse(p: &mut Parser<'a>) -> Result<Self> {
49 let name = p.parse::<T![Ident]>()?;
50 let colon = p.parse::<T![:]>()?;
51 let c: Cursor = name.into();
52 let value = <V>::parse_declaration_value(p, c)?;
53 let important = p.parse_if_peek::<BangImportant>()?;
54 let semicolon = p.parse_if_peek::<T![;]>()?;
55 Ok(Self { name, colon, value, important, semicolon, _phantom: PhantomData })
56 }
57}
58
59impl<'a, V: DeclarationValue<'a> + ToCursors> ToCursors for Declaration<'a, V> {
60 fn to_cursors(&self, s: &mut impl CursorSink) {
61 ToCursors::to_cursors(&self.name, s);
62 ToCursors::to_cursors(&self.colon, s);
63 ToCursors::to_cursors(&self.value, s);
64 ToCursors::to_cursors(&self.important, s);
65 ToCursors::to_cursors(&self.semicolon, s);
66 }
67}
68
69impl<'a, V: DeclarationValue<'a> + ToSpan> ToSpan for Declaration<'a, V> {
70 fn to_span(&self) -> Span {
71 self.name.to_span() + self.value.to_span() + self.important.to_span() + self.semicolon.to_span()
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use crate::test_helpers::*;
79
80 #[derive(Debug)]
81 struct Decl(T![Ident]);
82 impl<'a> DeclarationValue<'a> for Decl {
83 type ComputedValue = T![Eof];
84
85 fn is_initial(&self) -> bool {
86 false
87 }
88
89 fn is_inherit(&self) -> bool {
90 false
91 }
92
93 fn is_unset(&self) -> bool {
94 false
95 }
96
97 fn is_revert(&self) -> bool {
98 false
99 }
100
101 fn is_revert_layer(&self) -> bool {
102 false
103 }
104
105 fn needs_computing(&self) -> bool {
106 false
107 }
108
109 fn parse_specified_declaration_value(p: &mut Parser<'a>, _name: Cursor) -> Result<Self> {
110 p.parse::<T![Ident]>().map(Self)
111 }
112 }
113
114 impl ToCursors for Decl {
115 fn to_cursors(&self, s: &mut impl CursorSink) {
116 s.append(self.0.into())
117 }
118 }
119
120 impl ToSpan for Decl {
121 fn to_span(&self) -> Span {
122 self.0.to_span()
123 }
124 }
125
126 #[test]
127 fn size_test() {
128 assert_eq!(std::mem::size_of::<Declaration<Decl>>(), 80);
129 }
130
131 #[test]
132 fn test_writes() {
133 assert_parse!(Declaration<Decl>, "color:black;");
134 }
135}