path_value/
error.rs

1use core::result;
2use std::error::Error as StdError;
3use std::fmt;
4use std::io;
5
6use num_bigint::BigInt;
7use serde::de;
8use serde::ser;
9
10#[derive(Debug)]
11pub enum Unexpected {
12    Bool(bool),
13    Integer(BigInt),
14    Float(f64),
15    Str(String),
16    Unit,
17    Array,
18    Map,
19}
20
21impl fmt::Display for Unexpected {
22    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
23        match *self {
24            Unexpected::Bool(b) => write!(f, "boolean `{}`", b),
25            Unexpected::Integer(ref i) => write!(f, "integer `{}`", i),
26            Unexpected::Float(v) => write!(f, "floating point `{}`", v),
27            Unexpected::Str(ref s) => write!(f, "string {:?}", s),
28            Unexpected::Unit => write!(f, "unit value"),
29            Unexpected::Array => write!(f, "array"),
30            Unexpected::Map => write!(f, "map"),
31        }
32    }
33}
34
35pub struct Error {
36    inner: Box<ErrorImpl>,
37}
38
39pub type Result<T, E = Error> = result::Result<T, E>;
40
41impl From<io::Error> for Error {
42    fn from(source: io::Error) -> Self {
43        Error {
44            inner: Box::new(ErrorImpl::Io(source)),
45        }
46    }
47}
48
49impl From<std::convert::Infallible> for Error {
50    fn from(_: std::convert::Infallible) -> Self {
51        unreachable!()
52    }
53}
54
55impl Error {
56    #[doc(hidden)]
57    #[cold]
58    pub(crate) fn io(source: io::Error) -> Self {
59        Error {
60            inner: Box::new(ErrorImpl::Io(source)),
61        }
62    }
63
64    #[doc(hidden)]
65    #[cold]
66    pub(crate) fn too_large<T: Into<BigInt>>(index: T) -> Self {
67        Error {
68            inner: Box::new(ErrorImpl::Range(index.into())),
69        }
70    }
71
72    #[doc(hidden)]
73    #[cold]
74    pub(crate) fn invalid_type(unexpected: Unexpected, expected: &'static str) -> Self {
75        Error {
76            inner: Box::new(ErrorImpl::Type {
77                unexpected,
78                expected,
79            }),
80        }
81    }
82
83    #[doc(hidden)]
84    #[cold]
85    pub(crate) fn path_parse<R: pest::RuleType + Send + Sync + 'static>(
86        source: pest::error::Error<R>,
87        path: &str,
88    ) -> Self {
89        Error {
90            inner: Box::new(ErrorImpl::PathParse {
91                path: Box::from(path),
92                source: Box::new(source),
93            }),
94        }
95    }
96
97    #[doc(hidden)]
98    #[cold]
99    pub(crate) fn format_parse<E>(origin: &str, source: E) -> Self
100    where
101        E: StdError + Sync + Send + 'static,
102    {
103        Error {
104            inner: Box::new(ErrorImpl::FormatParse {
105                origin: origin.into(),
106                source: Box::new(source),
107            }),
108        }
109    }
110
111    #[doc(hidden)]
112    #[cold]
113    pub(crate) fn serde<T: AsRef<str>>(message: T) -> Self {
114        Error {
115            inner: Box::new(ErrorImpl::Serde(message.as_ref().into())),
116        }
117    }
118}
119
120impl fmt::Display for Error {
121    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122        fmt::Display::fmt(&*self.inner, f)
123    }
124}
125
126impl fmt::Debug for Error {
127    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
128        write!(f, "{}", *self)
129    }
130}
131
132impl StdError for Error {
133    fn source(&self) -> Option<&(dyn StdError + 'static)> {
134        match *self.inner {
135            ErrorImpl::PathParse { ref source, .. } => Some(source.as_ref()),
136
137            ErrorImpl::FormatParse { ref source, .. } => Some(source.as_ref()),
138
139            _ => None,
140        }
141    }
142}
143
144impl de::Error for Error {
145    fn custom<T: fmt::Display>(msg: T) -> Self {
146        Error {
147            inner: Box::new(ErrorImpl::Serde(msg.to_string().into())),
148        }
149    }
150}
151
152impl ser::Error for Error {
153    fn custom<T: fmt::Display>(msg: T) -> Self {
154        Error {
155            inner: Box::new(ErrorImpl::Serde(msg.to_string().into())),
156        }
157    }
158}
159
160/// Represents all possible errors that can occur when working with
161/// configuration.
162enum ErrorImpl {
163    /// Value path could not be parsed (Origin Path).
164    PathParse {
165        path: Box<str>,
166        source: Box<dyn StdError + Send + Sync>,
167    },
168
169    /// Some IO error occurred while file operation.
170    Io(io::Error),
171
172    /// Value could not be converted into the requested type.
173    Type {
174        /// What we found when parsing the value
175        unexpected: Unexpected,
176
177        /// What was expected when parsing the value
178        expected: &'static str,
179    },
180
181    /// Value could not be parsed by target format.
182    FormatParse {
183        origin: Box<str>,
184        source: Box<dyn StdError + Send + Sync>,
185    },
186
187    /// Serde error
188    Serde(Box<str>),
189
190    /// Path index over range
191    Range(BigInt),
192}
193
194impl fmt::Display for ErrorImpl {
195    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196        match *self {
197            ErrorImpl::PathParse {
198                ref path,
199                ref source,
200            } => write!(f, "{}\n for {}", source, path),
201
202            ErrorImpl::Range(ref i) => write!(f, "invalid range {}", i),
203
204            ErrorImpl::Type {
205                ref unexpected,
206                expected,
207            } => {
208                write!(f, "invalid type: {}, expected {}", unexpected, expected)?;
209                Ok(())
210            }
211
212            ErrorImpl::Io(ref err) => write!(f, "{}", err),
213
214            ErrorImpl::Serde(ref s) => write!(f, "{}", s),
215
216            ErrorImpl::FormatParse {
217                ref source,
218                ref origin,
219            } => {
220                write!(f, "{}\n in {}", source, origin)?;
221                Ok(())
222            }
223        }
224    }
225}