1use cssparser::{
2 AtRuleParser, ParseError, Parser, ParserInput, QualifiedRuleParser, StyleSheetParser,
3};
4use honzo_core::HonzoError;
5
6pub const CSS_TAG: [u8; 4] = *b"CSS_";
7
8pub fn is_css_tag(tag: &[u8; 4]) -> bool {
9 *tag == CSS_TAG
10}
11
12struct CssValidator;
13
14fn parse_entirely<'i, 't>(input: &mut Parser<'i, 't>) -> Result<(), ParseError<'i, ()>> {
15 while !input.is_exhausted() {
16 input.next()?;
17 }
18 Ok(())
19}
20
21impl<'i> QualifiedRuleParser<'i> for CssValidator {
22 type Prelude = ();
23 type QualifiedRule = ();
24 type Error = ();
25
26 fn parse_prelude<'t>(
27 &mut self,
28 input: &mut Parser<'i, 't>,
29 ) -> Result<Self::Prelude, ParseError<'i, Self::Error>> {
30 input.parse_entirely(parse_entirely)
31 }
32
33 fn parse_block<'t>(
34 &mut self,
35 _prelude: Self::Prelude,
36 _start: &cssparser::ParserState,
37 input: &mut Parser<'i, 't>,
38 ) -> Result<Self::QualifiedRule, ParseError<'i, Self::Error>> {
39 input.parse_entirely(parse_entirely)
40 }
41}
42
43impl<'i> AtRuleParser<'i> for CssValidator {
44 type Prelude = ();
45 type AtRule = ();
46 type Error = ();
47
48 fn parse_prelude<'t>(
49 &mut self,
50 _name: cssparser::CowRcStr<'i>,
51 input: &mut Parser<'i, 't>,
52 ) -> Result<Self::Prelude, ParseError<'i, Self::Error>> {
53 input.parse_entirely(parse_entirely)
54 }
55
56 fn parse_block<'t>(
57 &mut self,
58 _prelude: Self::Prelude,
59 _start: &cssparser::ParserState,
60 input: &mut Parser<'i, 't>,
61 ) -> Result<Self::AtRule, ParseError<'i, Self::Error>> {
62 input.parse_entirely(parse_entirely)
63 }
64
65 fn rule_without_block<'t>(
66 &mut self,
67 _prelude: Self::Prelude,
68 _start: &cssparser::ParserState,
69 ) -> Result<Self::AtRule, ()> {
70 Ok(())
71 }
72}
73
74pub fn validate_css(bytes: &[u8]) -> Result<&str, HonzoError> {
77 let s = core::str::from_utf8(bytes).map_err(|_| HonzoError::Truncated)?;
78 let mut input = ParserInput::new(s);
79 let mut parser = Parser::new(&mut input);
80 let mut validator = CssValidator;
81 let mut list_parser = StyleSheetParser::new(&mut parser, &mut validator);
82 loop {
83 match list_parser.next() {
84 Some(Ok(..)) => continue,
85 Some(Err((ParseError { .. }, _))) => return Err(HonzoError::InvalidCss),
86 None => break,
87 }
88 }
89 Ok(s)
90}
91
92pub fn validate_css_bytes(bytes: &[u8]) -> Result<(), u8> {
93 match validate_css(bytes) {
94 Ok(..) => Ok(()),
95 Err(HonzoError::Truncated) => Err(7),
96 Err(HonzoError::InvalidCss) => Err(8),
97 Err(..) => Err(255),
98 }
99}
100
101pub fn chunk_name() -> &'static str {
102 "stylesheet"
103}