use std::io;
use crate::*;
pub fn new_std_io_error(err: io::Error) -> Error {
use std::io::ErrorKind::*;
let (kind, retryable) = match err.kind() {
NotFound => (ErrorKind::NotFound, false),
PermissionDenied => (ErrorKind::PermissionDenied, false),
AlreadyExists => (ErrorKind::AlreadyExists, false),
Unsupported => (ErrorKind::Unsupported, false),
Interrupted | UnexpectedEof | TimedOut | WouldBlock => (ErrorKind::Unexpected, true),
_ => (ErrorKind::Unexpected, true),
};
let mut err = Error::new(kind, err.kind().to_string()).set_source(err);
if retryable {
err = err.set_temporary();
}
err
}
#[inline]
pub(crate) fn format_std_io_error(err: Error) -> io::Error {
let kind = match err.kind() {
ErrorKind::NotFound => io::ErrorKind::NotFound,
ErrorKind::PermissionDenied => io::ErrorKind::PermissionDenied,
_ => io::ErrorKind::Other,
};
io::Error::new(kind, err)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_read_to_end_stops_on_persistent_error() {
struct ErrorThenEof {
calls: usize,
}
impl io::Read for ErrorThenEof {
fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
self.calls += 1;
if self.calls == 1 {
return Err(format_std_io_error(
Error::new(ErrorKind::Unexpected, "retry exhausted").set_persistent(),
));
}
Ok(0)
}
}
let mut reader = ErrorThenEof { calls: 0 };
let mut buf = Vec::new();
assert!(
io::Read::read_to_end(&mut reader, &mut buf).is_err(),
"calls: {}",
reader.calls
);
}
}