css_parse/syntax/
component_values.rs1use crate::{
2 AssociatedWhitespaceRules, Cursor, CursorSink, DeclarationValue, Parse, Parser, Peek, Result, Span, ToCursors,
3 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(p: &Parser<'a>, c: Cursor) -> bool {
18 ComponentValue::peek(p, c)
19 }
20}
21
22impl<'a> Parse<'a> for ComponentValues<'a> {
23 fn parse(p: &mut Parser<'a>) -> Result<Self> {
25 let mut values = Vec::new_in(p.bump());
26 let mut last_was_whitespace = false;
27 loop {
28 if p.at_end() {
29 break;
30 }
31 if p.next_is_stop() {
32 break;
33 }
34 if p.peek::<ComponentValue>() {
35 let mut value = p.parse::<ComponentValue>()?;
36 if let ComponentValue::Delim(d) = value {
37 if last_was_whitespace {
38 let rules = d.associated_whitespace() | AssociatedWhitespaceRules::EnforceBefore;
39 value = ComponentValue::Delim(d.with_associated_whitespace(rules))
40 }
41 }
42 last_was_whitespace = matches!(value, ComponentValue::Whitespace(_));
43 values.push(value);
44 } else {
45 break;
46 }
47 }
48 Ok(Self { values })
49 }
50}
51
52impl<'a> DeclarationValue<'a> for ComponentValues<'a> {
53 type ComputedValue = ComponentValues<'a>;
54
55 fn is_initial(&self) -> bool {
56 false
57 }
58
59 fn is_inherit(&self) -> bool {
60 false
61 }
62
63 fn is_unset(&self) -> bool {
64 false
65 }
66
67 fn is_revert(&self) -> bool {
68 false
69 }
70
71 fn is_revert_layer(&self) -> bool {
72 false
73 }
74
75 fn needs_computing(&self) -> bool {
76 false
77 }
78
79 fn parse_custom_declaration_value(p: &mut Parser<'a>, _name: Cursor) -> Result<Self> {
80 Self::parse(p)
81 }
82
83 fn parse_computed_declaration_value(p: &mut Parser<'a>, _name: Cursor) -> Result<Self> {
84 Self::parse(p)
85 }
86
87 fn parse_unknown_declaration_value(p: &mut Parser<'a>, _name: Cursor) -> Result<Self> {
88 Self::parse(p)
89 }
90}
91
92impl<'a> ToCursors for ComponentValues<'a> {
93 fn to_cursors(&self, s: &mut impl CursorSink) {
94 ToCursors::to_cursors(&self.values, s)
95 }
96}
97
98impl<'a> ToSpan for ComponentValues<'a> {
99 fn to_span(&self) -> Span {
100 self.values.to_span()
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107 use crate::test_helpers::*;
108
109 #[test]
110 fn size_test() {
111 assert_eq!(std::mem::size_of::<ComponentValues>(), 32);
112 }
113
114 #[test]
115 fn test_writes() {
116 assert_parse!(ComponentValues, "body{color:black}");
117 assert_parse!(ComponentValues, "body");
118 }
119}