css_inline/
error.rs

1//! Errors that may happen during inlining.
2use cssparser::{BasicParseErrorKind, ParseError, ParseErrorKind};
3use std::{
4    borrow::Cow,
5    error::Error,
6    fmt,
7    fmt::{Display, Formatter},
8    io,
9};
10
11/// Inlining error
12#[derive(Debug)]
13pub enum InlineError {
14    /// Missing stylesheet file.
15    MissingStyleSheet {
16        /// Path to the missing file.
17        path: String,
18    },
19    /// Input-output error. May happen during writing the resulting HTML or retrieving a stylesheet
20    /// from the filesystem.
21    IO(io::Error),
22    /// Network-related problem. E.g. resource is not available.
23    #[cfg(feature = "http")]
24    Network {
25        /// Original network error.
26        error: reqwest::Error,
27        /// The stylesheet location caused the error.
28        location: String,
29    },
30    /// Syntax errors or unsupported selectors.
31    ParseError(Cow<'static, str>),
32}
33
34impl From<io::Error> for InlineError {
35    fn from(error: io::Error) -> Self {
36        Self::IO(error)
37    }
38}
39
40impl Error for InlineError {
41    fn source(&self) -> Option<&(dyn Error + 'static)> {
42        match self {
43            InlineError::IO(error) => Some(error),
44            #[cfg(feature = "http")]
45            InlineError::Network { error, .. } => Some(error),
46            InlineError::MissingStyleSheet { .. } | InlineError::ParseError(_) => None,
47        }
48    }
49}
50
51impl Display for InlineError {
52    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
53        match self {
54            Self::IO(error) => error.fmt(f),
55            #[cfg(feature = "http")]
56            Self::Network { error, location } => f.write_fmt(format_args!("{error}: {location}")),
57            Self::ParseError(error) => f.write_str(error),
58            Self::MissingStyleSheet { path } => {
59                f.write_fmt(format_args!("Missing stylesheet file: {path}"))
60            }
61        }
62    }
63}
64
65impl From<(ParseError<'_, ()>, &str)> for InlineError {
66    fn from(error: (ParseError<'_, ()>, &str)) -> Self {
67        match error.0.kind {
68            ParseErrorKind::Basic(kind) => match kind {
69                BasicParseErrorKind::UnexpectedToken(token) => {
70                    Self::ParseError(Cow::Owned(format!("Unexpected token: {token:?}")))
71                }
72                BasicParseErrorKind::EndOfInput => Self::ParseError(Cow::Borrowed("End of input")),
73                BasicParseErrorKind::AtRuleInvalid(value) => {
74                    Self::ParseError(Cow::Owned(format!("Invalid @ rule: {value}")))
75                }
76                BasicParseErrorKind::AtRuleBodyInvalid => {
77                    Self::ParseError(Cow::Borrowed("Invalid @ rule body"))
78                }
79                BasicParseErrorKind::QualifiedRuleInvalid => {
80                    Self::ParseError(Cow::Borrowed("Invalid qualified rule"))
81                }
82            },
83            ParseErrorKind::Custom(()) => Self::ParseError(Cow::Borrowed("Unknown error")),
84        }
85    }
86}