use std::{error, fmt, io};
#[derive(Clone, Debug)]
pub struct MalformedError(());
impl fmt::Display for MalformedError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "encountered a malformed byte sequence")
}
}
impl error::Error for MalformedError {}
impl MalformedError {
pub(crate) fn new() -> Self {
Self(())
}
pub(crate) fn wrap(self) -> io::Error {
io::Error::new(io::ErrorKind::InvalidData, self)
}
#[inline]
pub fn wrapped_in(io_error: &io::Error) -> Option<&Self> {
match io_error.get_ref() {
Some(e) => e.downcast_ref::<Self>(),
None => None,
}
}
}
#[derive(Clone, Debug)]
pub struct UnmappableError(char);
impl fmt::Display for UnmappableError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "encountered an unmappable character: {:?}", self.0)
}
}
impl error::Error for UnmappableError {}
impl UnmappableError {
pub(crate) fn new(unmappable_character: char) -> Self {
Self(unmappable_character)
}
pub(crate) fn wrap(self) -> io::Error {
io::Error::new(io::ErrorKind::InvalidData, self)
}
#[inline]
pub fn value(&self) -> char {
self.0
}
#[inline]
pub fn wrapped_in(io_error: &io::Error) -> Option<&Self> {
match io_error.get_ref() {
Some(e) => e.downcast_ref::<Self>(),
None => None,
}
}
}
#[cfg(test)]
mod tests {
use super::{io, MalformedError, UnmappableError};
#[test]
fn unwrap_malformed_error() {
assert!(MalformedError::wrapped_in(&io::Error::new(
io::ErrorKind::InvalidData,
MalformedError(())
))
.is_some());
assert!(MalformedError::wrapped_in(&io::Error::new(
io::ErrorKind::Other,
MalformedError(())
))
.is_some());
assert!(MalformedError::wrapped_in(&io::ErrorKind::InvalidData.into()).is_none());
assert!(MalformedError::wrapped_in(&io::ErrorKind::Other.into()).is_none());
assert!(MalformedError::wrapped_in(&io::Error::new(
io::ErrorKind::InvalidData,
"encountered a malformed byte sequence"
))
.is_none());
assert!(MalformedError::wrapped_in(&io::Error::new(
io::ErrorKind::Other,
"encountered a malformed byte sequence"
))
.is_none());
}
#[test]
fn unwrap_unmappable_error() {
assert!(UnmappableError::wrapped_in(&io::Error::new(
io::ErrorKind::InvalidData,
UnmappableError('.')
))
.is_some());
assert!(UnmappableError::wrapped_in(&io::Error::new(
io::ErrorKind::Other,
UnmappableError('.')
))
.is_some());
assert!(UnmappableError::wrapped_in(&io::ErrorKind::InvalidData.into()).is_none());
assert!(UnmappableError::wrapped_in(&io::ErrorKind::Other.into()).is_none());
assert!(UnmappableError::wrapped_in(&io::Error::new(
io::ErrorKind::InvalidData,
"encountered an unmappable character"
))
.is_none());
assert!(UnmappableError::wrapped_in(&io::Error::new(
io::ErrorKind::Other,
"encountered an unmappable character"
))
.is_none());
assert_eq!(
UnmappableError::wrapped_in(&io::Error::new(
io::ErrorKind::InvalidData,
UnmappableError('.')
))
.unwrap()
.value(),
'.'
);
assert_eq!(
UnmappableError::wrapped_in(&io::Error::new(
io::ErrorKind::Other,
UnmappableError('.')
))
.unwrap()
.value(),
'.'
);
}
}