serde_lexpr/
error.rs

1//! When serializing or deserializing S-expressions goes wrong.
2
3use std::fmt::{self, Debug, Display};
4use std::{error, io, result};
5
6use serde::{de, ser};
7
8use lexpr::parse;
9pub use lexpr::parse::error::Location;
10
11/// This type represents all possible errors that can occur when
12/// serializing or deserializing S-expression data.
13pub struct Error(Box<ErrorImpl>);
14
15/// Alias for a `Result` with the error type `serde_lexpr::Error`.
16pub type Result<T> = result::Result<T, Error>;
17
18enum ErrorImpl {
19    Message(String, Option<Location>),
20    Io(io::Error),
21    Parse(parse::Error),
22}
23
24impl Error {
25    /// Location of the error in the input stream.
26    pub fn location(&self) -> Option<Location> {
27        match &*self.0 {
28            ErrorImpl::Message(_, loc) => *loc,
29            ErrorImpl::Parse(e) => e.location(),
30            ErrorImpl::Io(_) => None,
31        }
32    }
33    /// Categorizes the cause of this error.
34    ///
35    /// - `Category::Io` - failure to read or write bytes on an IO stream
36    /// - `Category::Syntax` - input that is not a syntactically valid S-expression
37    /// - `Category::Data` - input data that is semantically incorrect
38    /// - `Category::Eof` - unexpected end of the input data
39    pub fn classify(&self) -> Category {
40        match &*self.0 {
41            ErrorImpl::Message(_, _) => Category::Data,
42            ErrorImpl::Io(_) => Category::Io,
43            ErrorImpl::Parse(e) => match e.classify() {
44                parse::error::Category::Syntax => Category::Syntax,
45                parse::error::Category::Io => Category::Io,
46                parse::error::Category::Eof => Category::Eof,
47            },
48        }
49    }
50}
51
52/// Categorizes the cause of a `serde_lexpr::Error`.
53#[derive(Copy, Clone, PartialEq, Eq, Debug)]
54pub enum Category {
55    /// The error was caused by a failure to read or bytes from an input source.
56    Io,
57
58    /// The error was caused by input that was not a syntactically valid
59    /// S-expression.
60    Syntax,
61
62    /// The error was caused by input data that was semantically incorrect.
63    ///
64    /// For example, an S-expression text representing a number is semantically
65    /// incorrect when the type being deserialized into holds a String.
66    Data,
67
68    /// The error was caused by prematurely reaching the end of the input data.
69    ///
70    /// Callers that process streaming input may be interested in retrying the
71    /// deserialization once more data is available.
72    Eof,
73}
74
75impl From<Error> for io::Error {
76    /// Convert a `serde_lexpr::Error` into an `io::Error`.
77    ///
78    /// S-expression syntax errors are turned into `InvalidData` IO errors.  EOF
79    /// errors are turned into `UnexpectedEof` IO errors.
80    ///
81    /// ```
82    /// use std::io;
83    ///
84    /// enum MyError {
85    ///     Io(io::Error),
86    ///     Lexpr(serde_lexpr::Error),
87    /// }
88    ///
89    /// impl From<serde_lexpr::Error> for MyError {
90    ///     fn from(err: serde_lexpr::Error) -> MyError {
91    ///         use serde_lexpr::error::Category;
92    ///         match err.classify() {
93    ///             Category::Io => {
94    ///                 MyError::Io(err.into())
95    ///             }
96    ///             Category::Syntax | Category::Eof | Category::Data => {
97    ///                 MyError::Lexpr(err)
98    ///             }
99    ///         }
100    ///     }
101    /// }
102    /// ```
103    fn from(l: Error) -> Self {
104        if let ErrorImpl::Io(err) = *l.0 {
105            err
106        } else {
107            match l.classify() {
108                Category::Io => unreachable!(),
109                Category::Syntax | Category::Data => io::Error::new(io::ErrorKind::InvalidData, l),
110                Category::Eof => io::Error::new(io::ErrorKind::UnexpectedEof, l),
111            }
112        }
113    }
114}
115
116impl error::Error for Error {
117    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
118        match &*self.0 {
119            ErrorImpl::Io(e) => Some(e),
120            ErrorImpl::Parse(e) => Some(e),
121            _ => None,
122        }
123    }
124}
125
126impl Display for Error {
127    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128        match &*self.0 {
129            ErrorImpl::Message(msg, _) => Display::fmt(msg, f),
130            ErrorImpl::Io(e) => Display::fmt(e, f),
131            ErrorImpl::Parse(e) => Display::fmt(e, f),
132        }
133    }
134}
135
136impl Debug for Error {
137    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
138        match &*self.0 {
139            ErrorImpl::Message(msg, loc) => formatter
140                .debug_tuple("Message")
141                .field(msg)
142                .field(loc)
143                .finish(),
144            ErrorImpl::Io(e) => formatter.debug_tuple("Io").field(e).finish(),
145            ErrorImpl::Parse(e) => formatter.debug_tuple("Parse").field(e).finish(),
146        }
147    }
148}
149
150impl de::Error for Error {
151    fn custom<T: Display>(msg: T) -> Error {
152        Error(Box::new(ErrorImpl::Message(msg.to_string(), None)))
153    }
154
155    fn invalid_type(unexp: de::Unexpected<'_>, exp: &dyn de::Expected) -> Self {
156        if let de::Unexpected::Unit = unexp {
157            Error::custom(format_args!("invalid type: null, expected {}", exp))
158        } else {
159            Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
160        }
161    }
162}
163
164impl ser::Error for Error {
165    fn custom<T: Display>(msg: T) -> Error {
166        Error(Box::new(ErrorImpl::Message(msg.to_string(), None)))
167    }
168}
169
170impl From<io::Error> for Error {
171    fn from(e: io::Error) -> Self {
172        Error(Box::new(ErrorImpl::Io(e)))
173    }
174}
175
176impl From<parse::Error> for Error {
177    fn from(e: parse::Error) -> Self {
178        Error(Box::new(ErrorImpl::Parse(e)))
179    }
180}