css_parse/syntax/
no_block_allowed.rs

1use crate::{Cursor, CursorSink, Parse, Parser, Peek, Result, Span, T, ToCursors, ToSpan, diagnostics};
2
3/// A struct to provide to [AtRule][crate::AtRule] to disallow blocks.
4///
5/// Sometimes [AtRules][crate::syntax::AtRule] do not have a block - for example `@charset`, `@import`. In those case, assigning
6/// this struct to the `Block` can be useful to ensure that the [AtRule][crate::syntax::AtRule] appropriately errors if it enters the
7/// Block parsing context. This captures the `;` token that may optionally end a "statement-style" at-rule.
8#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
10pub struct NoBlockAllowed(Option<T![;]>);
11
12impl<'a> Parse<'a> for NoBlockAllowed {
13	fn parse(p: &mut Parser<'a>) -> Result<Self> {
14		if p.at_end() {
15			Ok(Self(None))
16		} else if let Some(semicolon) = p.parse_if_peek::<T![;]>()? {
17			Ok(Self(Some(semicolon)))
18		} else {
19			Err(diagnostics::Unexpected(p.next()))?
20		}
21	}
22}
23
24impl<'a> Peek<'a> for NoBlockAllowed {
25	fn peek(_: &Parser<'a>, _: Cursor) -> bool {
26		false
27	}
28}
29
30impl ToCursors for NoBlockAllowed {
31	fn to_cursors(&self, s: &mut impl CursorSink) {
32		if let Some(semicolon) = self.0 {
33			s.append(semicolon.into());
34		}
35	}
36}
37
38impl ToSpan for NoBlockAllowed {
39	fn to_span(&self) -> Span {
40		self.0.to_span()
41	}
42}