css_parse/syntax/
simple_block.rs

1use crate::{
2	CursorSink, KindSet, Parse, Parser, Result as ParserResult, Span, T, ToCursors, ToSpan, syntax::ComponentValues,
3};
4
5#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(tag = "type"))]
7pub struct SimpleBlock<'a> {
8	pub open: T![PairWiseStart],
9	pub values: ComponentValues<'a>,
10	pub close: Option<T![PairWiseEnd]>,
11}
12
13// https://drafts.csswg.org/css-syntax-3/#consume-a-simple-block
14impl<'a> Parse<'a> for SimpleBlock<'a> {
15	fn parse(p: &mut Parser<'a>) -> ParserResult<Self> {
16		let open = p.parse::<T![PairWiseStart]>()?;
17		let stop = p.set_stop(KindSet::new(&[open.end()]));
18		let values = p.parse::<ComponentValues>();
19		p.set_stop(stop);
20		let values = values?;
21		if p.peek::<T![PairWiseEnd]>() {
22			return Ok(Self { open, values, close: p.parse::<T![PairWiseEnd]>().ok() });
23		}
24		Ok(Self { open, values, close: None })
25	}
26}
27
28impl<'a> ToCursors for SimpleBlock<'a> {
29	fn to_cursors(&self, s: &mut impl CursorSink) {
30		ToCursors::to_cursors(&self.open, s);
31		ToCursors::to_cursors(&self.values, s);
32		ToCursors::to_cursors(&self.close, s);
33	}
34}
35
36impl<'a> ToSpan for SimpleBlock<'a> {
37	fn to_span(&self) -> Span {
38		self.open.to_span() + if let Some(close) = self.close { close.to_span() } else { self.values.to_span() }
39	}
40}
41
42#[cfg(test)]
43mod tests {
44	use super::*;
45	use crate::test_helpers::*;
46
47	#[test]
48	fn size_test() {
49		assert_eq!(std::mem::size_of::<SimpleBlock>(), 64);
50	}
51
52	#[test]
53	fn test_writes() {
54		assert_parse!(SimpleBlock, "[foo]");
55		assert_parse!(SimpleBlock, "(one two three)");
56		assert_parse!(SimpleBlock, "{}");
57		assert_parse!(SimpleBlock, "{foo}");
58		assert_parse!(SimpleBlock, "{foo:bar}");
59		assert_parse!(SimpleBlock, "{one(two)}");
60		assert_parse!(SimpleBlock, "(one(two))");
61		// Incomplete but recoverable
62		assert_parse!(SimpleBlock, "[foo");
63		assert_parse!(SimpleBlock, "{foo:bar");
64		assert_parse!(SimpleBlock, "(one(two)");
65		assert_parse!(SimpleBlock, "(one(two");
66	}
67
68	#[test]
69	fn test_errors() {
70		assert_parse_error!(SimpleBlock, "foo");
71	}
72}