fetch_source/
error.rs

1//! Defines the error type for this crate.
2
3/// Errors that occur during fetching
4#[derive(Debug, thiserror::Error)]
5#[error("failed to fetch source")]
6pub struct FetchError {
7    source: crate::Source,
8    #[source]
9    err: FetchErrorKind,
10}
11
12impl FetchError {
13    pub(crate) fn new(err: FetchErrorKind, source: crate::Source) -> Self {
14        Self { source, err }
15    }
16}
17
18/// Internal error categories.
19#[derive(Debug, thiserror::Error)]
20pub(crate) enum FetchErrorKind {
21    #[error(transparent)]
22    Io(#[from] std::io::Error),
23
24    #[cfg(feature = "reqwest")]
25    #[error(transparent)]
26    Reqwest(#[from] reqwest::Error),
27
28    #[error("subprocess '{command}' exited with status {status}\n{stderr}")]
29    Subprocess {
30        command: String,
31        status: std::process::ExitStatus,
32        stderr: String,
33    },
34}
35
36impl FetchErrorKind {
37    pub fn subprocess(command: String, status: std::process::ExitStatus, stderr: String) -> Self {
38        Self::Subprocess {
39            command,
40            status,
41            stderr,
42        }
43    }
44}
45
46/// The main error type for this crate.
47#[derive(Debug, thiserror::Error)]
48pub struct Error {
49    kind: ErrorKind,
50    inner: ErrorImpl,
51}
52
53impl std::fmt::Display for Error {
54    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55        write!(f, "{}", self.inner)
56    }
57}
58
59impl Error {
60    /// Get the kind of error that occurred
61    pub fn kind(&self) -> &ErrorKind {
62        &self.kind
63    }
64}
65
66/// The different kinds of error that can be emitted by this crate.
67#[derive(Debug, PartialEq, Eq)]
68pub enum ErrorKind {
69    /// An I/O error occurred
70    Io,
71    #[cfg(feature = "reqwest")]
72    /// An `Reqwest` error occurred
73    Reqwest,
74    /// A TOML deserialisation error occurred
75    TomlDe,
76    /// A serde deserialisation error occurred
77    SerdeDe,
78    /// An error occurred while parsing sources
79    Parse,
80}
81
82/// Internal error categories.
83#[derive(Debug, thiserror::Error)]
84pub(crate) enum ErrorImpl {
85    #[error(transparent)]
86    Io(#[from] std::io::Error),
87
88    #[cfg(feature = "reqwest")]
89    #[error(transparent)]
90    Reqwest(#[from] reqwest::Error),
91
92    #[error(transparent)]
93    TomlDe(#[from] toml::de::Error),
94
95    #[error(transparent)]
96    SerdeDe(#[from] serde_json::Error),
97
98    #[error(transparent)]
99    Parse(#[from] crate::SourceParseError),
100}
101
102impl ErrorImpl {
103    fn into_error<T>(value: T) -> Error
104    where
105        ErrorImpl: From<T>,
106    {
107        let inner = ErrorImpl::from(value);
108        let kind = match &inner {
109            Self::Io(_) => ErrorKind::Io,
110            #[cfg(feature = "reqwest")]
111            Self::Reqwest(_) => ErrorKind::Reqwest,
112            Self::TomlDe(_) => ErrorKind::TomlDe,
113            Self::SerdeDe(_) => ErrorKind::SerdeDe,
114            Self::Parse(_) => ErrorKind::Parse,
115        };
116        Error { kind, inner }
117    }
118}
119
120// Blanket implementation for all variants of ErrorKind with a #[from] attribute
121impl<T> From<T> for Error
122where
123    ErrorImpl: From<T>,
124{
125    fn from(err: T) -> Self {
126        ErrorImpl::into_error(err)
127    }
128}