use crate::fs::{PathBuf, PathError};
use alloc::string::FromUtf8Error;
use core::fmt::Debug;
use core::fmt::{self, Display, Formatter};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Error {
    Io(IoError),
    Path(PathError),
    Utf8Encoding(FromUtf8Error),
}
impl Display for Error {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Self::Io(_) => write!(f, "IO error"),
            Self::Path(_) => write!(f, "path error"),
            Self::Utf8Encoding(_) => write!(f, "UTF-8 encoding error"),
        }
    }
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IoError {
    pub path: PathBuf,
    pub context: IoErrorContext,
    pub uefi_error: crate::Error,
}
impl Display for IoError {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "IO error for path {}: {}", self.path, self.context)
    }
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum IoErrorContext {
    CantDeleteDirectory,
    CantDeleteFile,
    FlushFailure,
    CantOpenVolume,
    Metadata,
    OpenError,
    ReadFailure,
    WriteFailure,
    NotADirectory,
    NotAFile,
}
impl Display for IoErrorContext {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        let s = match self {
            Self::CantDeleteDirectory => "failed to delete directory",
            Self::CantDeleteFile => "failed to delete file",
            Self::FlushFailure => "failed to flush file",
            Self::CantOpenVolume => "failed to open volume",
            Self::Metadata => "failed to read metadata",
            Self::OpenError => "failed to open file",
            Self::ReadFailure => "failed to read file",
            Self::WriteFailure => "failed to write file",
            Self::NotADirectory => "expected a directory",
            Self::NotAFile => "expected a file",
        };
        write!(f, "{s}")
    }
}
impl From<PathError> for Error {
    fn from(value: PathError) -> Self {
        Self::Path(value)
    }
}
#[cfg(feature = "unstable")]
impl core::error::Error for Error {
    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
        match self {
            Error::Io(err) => Some(err),
            Error::Path(err) => Some(err),
            Error::Utf8Encoding(err) => Some(err),
        }
    }
}
#[cfg(feature = "unstable")]
impl core::error::Error for IoError {
    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
        Some(&self.uefi_error)
    }
}