scraper/
error.rs

1//! Custom error types for diagnostics
2//! Includes re-exported error types from dependencies
3
4mod utils;
5
6use std::{error::Error, fmt::Display};
7
8use cssparser::{BasicParseErrorKind, ParseErrorKind, Token};
9use selectors::parser::SelectorParseErrorKind;
10
11/// Error type that is returned when calling `Selector::parse`
12#[derive(Debug, Clone)]
13pub enum SelectorErrorKind<'a> {
14    /// A `Token` was not expected
15    UnexpectedToken(Token<'a>),
16
17    /// End-Of-Line was unexpected
18    EndOfLine,
19
20    /// `@` rule is invalid
21    InvalidAtRule(String),
22
23    /// The body of an `@` rule is invalid
24    InvalidAtRuleBody,
25
26    /// The qualified rule is invalid
27    QualRuleInvalid,
28
29    /// Expected a `::` for a pseudoelement
30    ExpectedColonOnPseudoElement(Token<'a>),
31
32    /// Expected an identity for a pseudoelement
33    ExpectedIdentityOnPseudoElement(Token<'a>),
34
35    /// A `SelectorParseErrorKind` error that isn't really supposed to happen did
36    UnexpectedSelectorParseError(SelectorParseErrorKind<'a>),
37}
38
39impl<'a> From<cssparser::ParseError<'a, SelectorParseErrorKind<'a>>> for SelectorErrorKind<'a> {
40    fn from(original: cssparser::ParseError<'a, SelectorParseErrorKind<'a>>) -> Self {
41        // NOTE: This could be improved, but I dont
42        // exactly know how
43        match original.kind {
44            ParseErrorKind::Basic(err) => SelectorErrorKind::from(err),
45            ParseErrorKind::Custom(err) => SelectorErrorKind::from(err),
46        }
47    }
48}
49
50impl<'a> From<BasicParseErrorKind<'a>> for SelectorErrorKind<'a> {
51    fn from(err: BasicParseErrorKind<'a>) -> Self {
52        match err {
53            BasicParseErrorKind::UnexpectedToken(token) => Self::UnexpectedToken(token),
54            BasicParseErrorKind::EndOfInput => Self::EndOfLine,
55            BasicParseErrorKind::AtRuleInvalid(rule) => Self::InvalidAtRule(rule.to_string()),
56            BasicParseErrorKind::AtRuleBodyInvalid => Self::InvalidAtRuleBody,
57            BasicParseErrorKind::QualifiedRuleInvalid => Self::QualRuleInvalid,
58        }
59    }
60}
61
62impl<'a> From<SelectorParseErrorKind<'a>> for SelectorErrorKind<'a> {
63    fn from(err: SelectorParseErrorKind<'a>) -> Self {
64        match err {
65            SelectorParseErrorKind::PseudoElementExpectedColon(token) => {
66                Self::ExpectedColonOnPseudoElement(token)
67            }
68            SelectorParseErrorKind::PseudoElementExpectedIdent(token) => {
69                Self::ExpectedIdentityOnPseudoElement(token)
70            }
71            other => Self::UnexpectedSelectorParseError(other),
72        }
73    }
74}
75
76impl Display for SelectorErrorKind<'_> {
77    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78        write!(
79            f,
80            "{}",
81            match self {
82                Self::UnexpectedToken(token) => {
83                    format!("Token {:?} was not expected", utils::render_token(token))
84                }
85                Self::EndOfLine => "Unexpected EOL".to_string(),
86                Self::InvalidAtRule(rule) => format!("Invalid @-rule {:?}", rule),
87                Self::InvalidAtRuleBody => "The body of an @-rule was invalid".to_string(),
88                Self::QualRuleInvalid => "The qualified name was invalid".to_string(),
89                Self::ExpectedColonOnPseudoElement(token) => format!(
90                    "Expected a ':' token for pseudoelement, got {:?} instead",
91                    utils::render_token(token)
92                ),
93                Self::ExpectedIdentityOnPseudoElement(token) => format!(
94                    "Expected identity for pseudoelement, got {:?} instead",
95                    utils::render_token(token)
96                ),
97                Self::UnexpectedSelectorParseError(err) => format!(
98                    "Unexpected error occurred. Please report this to the developer\n{:#?}",
99                    err
100                ),
101            }
102        )
103    }
104}
105
106impl Error for SelectorErrorKind<'_> {
107    fn description(&self) -> &str {
108        match self {
109            Self::UnexpectedToken(_) => "Token was not expected",
110            Self::EndOfLine => "Unexpected EOL",
111            Self::InvalidAtRule(_) => "Invalid @-rule",
112            Self::InvalidAtRuleBody => "The body of an @-rule was invalid",
113            Self::QualRuleInvalid => "The qualified name was invalid",
114            Self::ExpectedColonOnPseudoElement(_) => "Missing colon character on pseudoelement",
115            Self::ExpectedIdentityOnPseudoElement(_) => "Missing pseudoelement identity",
116            Self::UnexpectedSelectorParseError(_) => "Unexpected error",
117        }
118    }
119}