Skip to main content

hjkl_css/
error.rs

1use cssparser::{BasicParseErrorKind, ParseErrorKind};
2use thiserror::Error;
3
4/// Failure modes for [`crate::parse`]. The current implementation is
5/// lenient — malformed rules and declarations are dropped silently per
6/// CSS spec, so a normal `parse` call never returns this. The type is
7/// preserved on the public API so a future strict-mode entry point can
8/// surface diagnostics without a breaking change.
9#[derive(Debug, Error)]
10#[non_exhaustive]
11pub enum ParseError {
12    #[error("CSS syntax error at line {line}, col {column}: {message}")]
13    Syntax {
14        line: u32,
15        column: u32,
16        message: String,
17    },
18}
19
20impl<'i> From<cssparser::ParseError<'i, ParseErrorOwned>> for ParseError {
21    fn from(err: cssparser::ParseError<'i, ParseErrorOwned>) -> Self {
22        let location = err.location;
23        let message = match err.kind {
24            ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(t)) => {
25                format!("unexpected token: {t:?}")
26            }
27            ParseErrorKind::Basic(BasicParseErrorKind::EndOfInput) => {
28                "unexpected end of input".to_string()
29            }
30            ParseErrorKind::Basic(BasicParseErrorKind::AtRuleInvalid(s)) => {
31                format!("invalid @-rule: {s}")
32            }
33            ParseErrorKind::Basic(BasicParseErrorKind::AtRuleBodyInvalid) => {
34                "invalid @-rule body".to_string()
35            }
36            ParseErrorKind::Basic(BasicParseErrorKind::QualifiedRuleInvalid) => {
37                "invalid rule".to_string()
38            }
39            ParseErrorKind::Custom(c) => c.0,
40        };
41        Self::Syntax {
42            line: location.line,
43            column: location.column,
44            message,
45        }
46    }
47}
48
49/// Internal error type for the cssparser parser plumbing. Wraps a message
50/// so the `'i` lifetime stays clean. Not part of the public API — leaks
51/// out only inside `cssparser::ParseError`, which we convert to
52/// [`ParseError`] at the boundary.
53#[derive(Debug, Clone, PartialEq, Eq)]
54pub(crate) struct ParseErrorOwned(pub String);