css_parse/syntax/
component_values.rs1use crate::{
2 AssociatedWhitespaceRules, Cursor, CursorSink, DeclarationValue, KindSet, NodeMetadata, NodeWithMetadata, Parse,
3 Parser, Peek, Result, SemanticEq, Span, ToCursors, ToSpan, Vec,
4};
5
6use super::ComponentValue;
7use csskit_proc_macro::node;
8
9#[node]
11#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
13pub struct ComponentValues<'a> {
14 values: Vec<'a, ComponentValue<'a>>,
15}
16
17impl<'a> Peek<'a> for ComponentValues<'a> {
18 const PEEK_KINDSET: KindSet = ComponentValue::PEEK_KINDSET;
19}
20
21impl<'a> Parse<'a> for ComponentValues<'a> {
22 fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
24 where
25 Iter: Iterator<Item = Cursor> + Clone,
26 {
27 let mut values = Vec::new_in(p.alloc());
28 let mut last_was_whitespace = false;
29
30 loop {
31 if p.at_end() {
32 break;
33 }
34 if p.next_is_stop() {
35 break;
36 }
37 if let Some(mut value) = p.parse_if_peek::<ComponentValue>()? {
38 if let ComponentValue::Delim(d) = value
39 && last_was_whitespace
40 && d.associated_whitespace().contains(AssociatedWhitespaceRules::EnforceAfter)
41 {
42 let rules = d.associated_whitespace() | AssociatedWhitespaceRules::EnforceBefore;
43 value = ComponentValue::Delim(d.with_associated_whitespace(rules))
44 }
45 last_was_whitespace = matches!(value, ComponentValue::Whitespace(_));
46 values.push(value);
47 } else {
48 break;
49 }
50 }
51 Ok(Self { values })
52 }
53}
54
55impl<'a, M: NodeMetadata> NodeWithMetadata<M> for ComponentValues<'a> {
56 fn metadata(&self) -> M {
57 M::default()
58 }
59}
60
61impl<'a> DeclarationValue<'a, ()> for ComponentValues<'a> {
62 fn is_initial(&self) -> bool {
63 false
64 }
65
66 fn is_inherit(&self) -> bool {
67 false
68 }
69
70 fn is_unset(&self) -> bool {
71 false
72 }
73
74 fn is_revert(&self) -> bool {
75 false
76 }
77
78 fn is_revert_layer(&self) -> bool {
79 false
80 }
81
82 fn needs_computing(&self) -> bool {
83 false
84 }
85
86 fn parse_custom_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _name: Cursor) -> Result<Self>
87 where
88 Iter: Iterator<Item = crate::Cursor> + Clone,
89 {
90 Self::parse(p)
91 }
92
93 fn is_computed_declaration_value<Iter>(p: &Parser<'a, Iter>, c: Cursor) -> bool
94 where
95 Iter: Iterator<Item = crate::Cursor> + Clone,
96 {
97 <Self as Peek>::peek(p, c)
98 }
99
100 fn parse_computed_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _name: Cursor) -> Result<Self>
101 where
102 Iter: Iterator<Item = crate::Cursor> + Clone,
103 {
104 Self::parse(p)
105 }
106
107 fn parse_unknown_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _name: Cursor) -> Result<Self>
108 where
109 Iter: Iterator<Item = crate::Cursor> + Clone,
110 {
111 Self::parse(p)
112 }
113}
114
115impl<'a> ToCursors for ComponentValues<'a> {
116 fn to_cursors(&self, s: &mut impl CursorSink) {
117 ToCursors::to_cursors(&self.values, s)
118 }
119}
120
121impl<'a> ToSpan for ComponentValues<'a> {
122 fn to_span(&self) -> Span {
123 self.values.to_span()
124 }
125}
126
127impl<'a> SemanticEq for ComponentValues<'a> {
129 fn semantic_eq(&self, other: &Self) -> bool {
130 self.values.semantic_eq(&other.values)
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137 use crate::{EmptyAtomSet, test_helpers::*};
138
139 #[test]
140 fn test_writes() {
141 assert_parse!(EmptyAtomSet::ATOMS, ComponentValues, "body{color:black}");
142 assert_parse!(EmptyAtomSet::ATOMS, ComponentValues, "body");
143 }
144
145 #[test]
146 fn test_writes_with_trivia() {
147 assert_parse!(EmptyAtomSet::ATOMS, ComponentValues, "/*comment*/foo");
148 assert_parse!(EmptyAtomSet::ATOMS, ComponentValues, " /*comment*/ foo");
149 assert_parse!(EmptyAtomSet::ATOMS, ComponentValues, "/*a*/foo/*b*/bar");
150 assert_parse!(EmptyAtomSet::ATOMS, ComponentValues, "foo/*comment*/bar");
151 assert_parse!(EmptyAtomSet::ATOMS, ComponentValues, " \t foo");
152 assert_parse!(EmptyAtomSet::ATOMS, ComponentValues, " /*start*/ foo /*mid*/ bar");
153 assert_parse!(EmptyAtomSet::ATOMS, ComponentValues, "/*comment*/foo");
154 }
155}