Skip to content

Commit 8b681ff

Browse files
authored
Merge pull request #1026 from dtolnay/errorkind
Add Error::io_error_kind
2 parents 136b773 + 9308d97 commit 8b681ff

File tree

1 file changed

+53
-2
lines changed

1 file changed

+53
-2
lines changed

src/error.rs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use core::str::FromStr;
99
use serde::{de, ser};
1010
#[cfg(feature = "std")]
1111
use std::error;
12+
#[cfg(feature = "std")]
13+
use std::io::ErrorKind;
1214

1315
/// This type represents all possible errors that can occur when serializing or
1416
/// deserializing JSON data.
@@ -105,6 +107,55 @@ impl Error {
105107
pub fn is_eof(&self) -> bool {
106108
self.classify() == Category::Eof
107109
}
110+
111+
/// The kind reported by the underlying standard library I/O error, if this
112+
/// error was caused by a failure to read or write bytes on an I/O stream.
113+
///
114+
/// # Example
115+
///
116+
/// ```
117+
/// use serde_json::Value;
118+
/// use std::io::{self, ErrorKind, Read};
119+
/// use std::process;
120+
///
121+
/// struct ReaderThatWillTimeOut<'a>(&'a [u8]);
122+
///
123+
/// impl<'a> Read for ReaderThatWillTimeOut<'a> {
124+
/// fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
125+
/// if self.0.is_empty() {
126+
/// Err(io::Error::new(ErrorKind::TimedOut, "timed out"))
127+
/// } else {
128+
/// self.0.read(buf)
129+
/// }
130+
/// }
131+
/// }
132+
///
133+
/// fn main() {
134+
/// let reader = ReaderThatWillTimeOut(br#" {"k": "#);
135+
///
136+
/// let _: Value = match serde_json::from_reader(reader) {
137+
/// Ok(value) => value,
138+
/// Err(error) => {
139+
/// if error.io_error_kind() == Some(ErrorKind::TimedOut) {
140+
/// // Maybe this application needs to retry certain kinds of errors.
141+
///
142+
/// # return;
143+
/// } else {
144+
/// eprintln!("error: {}", error);
145+
/// process::exit(1);
146+
/// }
147+
/// }
148+
/// };
149+
/// }
150+
/// ```
151+
#[cfg(feature = "std")]
152+
pub fn io_error_kind(&self) -> Option<ErrorKind> {
153+
if let ErrorCode::Io(io_error) = &self.err.code {
154+
Some(io_error.kind())
155+
} else {
156+
None
157+
}
158+
}
108159
}
109160

110161
/// Categorizes the cause of a `serde_json::Error`.
@@ -166,8 +217,8 @@ impl From<Error> for io::Error {
166217
} else {
167218
match j.classify() {
168219
Category::Io => unreachable!(),
169-
Category::Syntax | Category::Data => io::Error::new(io::ErrorKind::InvalidData, j),
170-
Category::Eof => io::Error::new(io::ErrorKind::UnexpectedEof, j),
220+
Category::Syntax | Category::Data => io::Error::new(ErrorKind::InvalidData, j),
221+
Category::Eof => io::Error::new(ErrorKind::UnexpectedEof, j),
171222
}
172223
}
173224
}

0 commit comments

Comments
 (0)