use std::error;
use std::fmt;
use std::io;
use std::result;
use crate::prelude::PathType;
use crate::prelude::VfsCore;
use crate::traits::vfs;
use crate::traits::vfs::OwnedPathType;
#[derive(Debug)]
pub enum Error<P> {
Io(P, io::Error),
Parse(P, Box<dyn error::Error + Send + Sync>),
Write(P, Box<dyn error::Error + Send + Sync>),
Serde(P, Box<dyn error::Error + Send + Sync>),
}
impl<P: fmt::Debug> error::Error for Error<P> {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
Self::Io(_, e) => Some(e),
Self::Parse(_, e) => Some(e.as_ref()),
Self::Write(_, e) => Some(e.as_ref()),
Self::Serde(_, e) => Some(e.as_ref()),
}
}
}
impl<P: fmt::Debug> fmt::Display for Error<P> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Io(path, e) => write!(f, "IO error at {:?}: {}", path, e),
Self::Parse(path, e) => write!(f, "Parse error at {:?}: {}", path, e),
Self::Write(path, e) => write!(f, "Write error at {:?}: {}", path, e),
Self::Serde(path, e) => write!(f, "Serde error at {:?}: {}", path, e),
}
}
}
mod sealed {
use std::io;
pub trait Sealed {}
impl<T> Sealed for io::Result<T> {}
}
pub trait WrapIoError<PathType: vfs::PathType + ?Sized>: Sized + sealed::Sealed {
type Output;
fn wrap_io_error(
self,
get_path: impl FnOnce() -> PathType::OwnedPath,
) -> Result<Self::Output, PathType::OwnedPath>;
fn wrap_io_error_with(self, path: &PathType) -> Result<Self::Output, PathType::OwnedPath> {
self.wrap_io_error(|| path.owned())
}
}
impl<T, P: vfs::PathType + ?Sized> WrapIoError<P> for io::Result<T> {
type Output = T;
fn wrap_io_error(
self,
get_path: impl FnOnce() -> P::OwnedPath,
) -> Result<Self::Output, P::OwnedPath> {
self.map_err(|e| Error::Io(get_path(), e))
}
}
#[expect(type_alias_bounds)]
pub type Result<T, P: OwnedPathType> = result::Result<T, Error<P>>;
#[expect(type_alias_bounds)]
pub type VfsResult<T, Vfs: VfsCore> = Result<T, <Vfs::Path as PathType>::OwnedPath>;