dts_core/
error.rs

1//! Defines the `Error` and `Result` types used by this crate.
2
3use crate::{parsers::ParseError, Encoding};
4use std::error::Error as StdError;
5use std::fmt::Display;
6use std::io;
7use thiserror::Error;
8
9/// A type alias for `Result<T, Error>`.
10pub type Result<T, E = Error> = std::result::Result<T, E>;
11
12/// The error returned by all fallible operations within this crate.
13#[non_exhaustive]
14#[derive(Error, Debug)]
15pub enum Error {
16    /// Represents a generic error message.
17    #[error("{0}")]
18    Message(String),
19
20    /// Represents errors of operations that are not supported by a certain encoding.
21    #[error("operation is not supported for encoding `{0}`")]
22    UnsupportedEncoding(Encoding),
23
24    /// Error emitted by parsers from this crate.
25    #[error(transparent)]
26    ParseError(#[from] ParseError),
27
28    /// Represents generic IO errors.
29    #[error(transparent)]
30    Io(#[from] io::Error),
31
32    /// Represents an invalid glob pattern.
33    #[error("invalid glob pattern `{pattern}`")]
34    GlobPatternError {
35        /// The pattern that caused the error.
36        pattern: String,
37        /// The underlying error.
38        source: glob::PatternError,
39    },
40
41    /// Represents an error fetching a remote data source.
42    #[error("unable to fetch remote data source")]
43    RequestError(#[from] ureq::Error),
44
45    /// Represents errors emitted by serializers and deserializers.
46    #[error(transparent)]
47    Serde(Box<dyn StdError + Send + Sync>),
48}
49
50impl Error {
51    pub(crate) fn new<T>(msg: T) -> Error
52    where
53        T: Display,
54    {
55        Error::Message(msg.to_string())
56    }
57
58    pub(crate) fn serde<E>(err: E) -> Error
59    where
60        E: Into<Box<dyn StdError + Send + Sync>>,
61    {
62        Error::Serde(err.into())
63    }
64
65    pub(crate) fn io<E>(err: E) -> Error
66    where
67        E: Into<io::Error>,
68    {
69        Error::Io(err.into())
70    }
71
72    pub(crate) fn glob_pattern<T>(pattern: T, source: glob::PatternError) -> Error
73    where
74        T: Display,
75    {
76        Error::GlobPatternError {
77            pattern: pattern.to_string(),
78            source,
79        }
80    }
81}
82
83impl From<serde_json::Error> for Error {
84    fn from(err: serde_json::Error) -> Self {
85        if err.is_io() {
86            Error::io(err)
87        } else {
88            Error::serde(err)
89        }
90    }
91}
92
93impl From<serde_yaml::Error> for Error {
94    fn from(err: serde_yaml::Error) -> Self {
95        if let Some(source) = err.source() {
96            if let Some(io_err) = source.downcast_ref::<io::Error>() {
97                return Error::io(io_err.kind());
98            }
99        }
100
101        Error::serde(err)
102    }
103}
104
105impl From<json5::Error> for Error {
106    fn from(err: json5::Error) -> Self {
107        Error::serde(err)
108    }
109}
110
111impl From<toml::ser::Error> for Error {
112    fn from(err: toml::ser::Error) -> Self {
113        Error::serde(err)
114    }
115}
116
117impl From<toml::de::Error> for Error {
118    fn from(err: toml::de::Error) -> Self {
119        Error::serde(err)
120    }
121}
122
123impl From<csv::Error> for Error {
124    fn from(err: csv::Error) -> Self {
125        if err.is_io_error() {
126            match err.into_kind() {
127                csv::ErrorKind::Io(io_err) => Error::io(io_err),
128                _ => unreachable!(),
129            }
130        } else {
131            Error::serde(err)
132        }
133    }
134}
135
136impl From<serde_qs::Error> for Error {
137    fn from(err: serde_qs::Error) -> Self {
138        match err {
139            serde_qs::Error::Io(io_err) => Error::io(io_err),
140            other => Error::serde(other),
141        }
142    }
143}
144
145impl From<serde_xml_rs::Error> for Error {
146    fn from(err: serde_xml_rs::Error) -> Self {
147        match err {
148            serde_xml_rs::Error::Io { source } => Error::io(source),
149            other => Error::serde(other),
150        }
151    }
152}
153
154impl From<hcl::Error> for Error {
155    fn from(err: hcl::Error) -> Self {
156        match err {
157            hcl::Error::Io(io_err) => Error::io(io_err),
158            other => Error::serde(other),
159        }
160    }
161}