use std::cmp::Ordering;
use std::io;
use std::fmt::{Debug, Display, Formatter, self};
use std::error::Error as StdError;
use std::hash::{Hash, Hasher};
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Default, Debug)]
pub struct WriteCounter {
pub count: usize,
}
impl io::Write for WriteCounter {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let len = buf.len();
self.count += len;
Ok(len)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
pub struct IoError {
kind: io::ErrorKind,
display: String,
debug: String,
details: Option<Box<dyn StdError + Send + Sync>>,
}
impl IoError {
pub fn kind(&self) -> io::ErrorKind {
self.kind
}
}
impl Clone for IoError {
fn clone(&self) -> Self {
Self {
kind: self.kind,
display: self.display.clone(),
debug: self.debug.clone(),
details: None,
}
}
}
impl PartialEq for IoError {
fn eq(&self, other: &Self) -> bool {
self.kind == other.kind && self.debug == other.debug
}
}
impl Eq for IoError {}
impl PartialOrd for IoError {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for IoError {
fn cmp(&self, other: &Self) -> Ordering {
match self.kind.cmp(&other.kind) {
Ordering::Equal => self.debug.cmp(&other.debug),
ordering => ordering,
}
}
}
impl Hash for IoError {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write(self.debug.as_bytes())
}
}
impl Display for IoError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let err = io::Error::from(self.clone());
Display::fmt(&err, f)
}
}
impl Debug for IoError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let err = io::Error::from(self.clone());
Debug::fmt(&err, f)
}
}
impl std::error::Error for IoError {}
impl From<io::Error> for IoError {
fn from(err: io::Error) -> Self {
IoError {
kind: err.kind(),
display: err.to_string(),
debug: format!("{:?}", err),
details: err.into_inner(),
}
}
}
impl From<io::ErrorKind> for IoError {
fn from(kind: io::ErrorKind) -> Self {
IoError {
kind,
display: kind.to_string(),
debug: format!("{:?}", kind),
details: None,
}
}
}
impl From<IoError> for io::Error {
fn from(err: IoError) -> Self {
match err.details {
Some(details) => io::Error::new(err.kind, details),
None => io::Error::from(err.kind),
}
}
}