use std::borrow::Cow;
use std::path::{Path, PathBuf};
use std::{fmt, io};
#[derive(Debug, Clone)]
pub struct SoftCanonicalizeError {
path: PathBuf,
detail: Cow<'static, str>,
}
impl SoftCanonicalizeError {
pub fn new(path: PathBuf, detail: impl Into<Cow<'static, str>>) -> Self {
Self {
path,
detail: detail.into(),
}
}
pub fn path(&self) -> &Path {
&self.path
}
pub fn detail(&self) -> &str {
&self.detail
}
}
impl fmt::Display for SoftCanonicalizeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} (path: '{}')", self.detail, self.path.display())
}
}
impl std::error::Error for SoftCanonicalizeError {}
#[inline]
pub(crate) fn error_with_path(
kind: io::ErrorKind,
path: &Path,
detail: impl Into<Cow<'static, str>>,
) -> io::Error {
io::Error::new(kind, SoftCanonicalizeError::new(path.to_path_buf(), detail))
}
pub trait IoErrorPathExt {
fn offending_path(&self) -> Option<&Path>;
fn soft_canon_detail(&self) -> Option<&str>;
}
impl IoErrorPathExt for io::Error {
fn offending_path(&self) -> Option<&Path> {
self.get_ref()
.and_then(|e| e.downcast_ref::<SoftCanonicalizeError>())
.map(|p| p.path())
}
fn soft_canon_detail(&self) -> Option<&str> {
self.get_ref()
.and_then(|e| e.downcast_ref::<SoftCanonicalizeError>())
.map(|p| p.detail())
}
}