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