chdlady-disc 0.2.2

Disc geometries and physical media formats for chdlady
//! Error types for disc media operations.
use chdlady_core::ChdError;
use std::fmt;
use std::io;

/// Errors that can occur during disc or optical media operations.
#[derive(Debug)]
pub enum DiscError {
    /// An I/O error occurred.
    Io(io::Error),
    /// An underlying CHD container error occurred.
    Chd(ChdError),
    /// A WAV audio file error occurred.
    Hound(hound::Error),
    /// Failed to parse or validate a CUE sheet.
    InvalidCue(String),
    /// Failed to parse or validate a GDI file.
    InvalidGdi(String),
    /// Failed to parse or validate a CDRDAO TOC file.
    InvalidToc(String),
    /// Failed to parse or validate a CloneCD CCD file.
    InvalidCcd(String),
    /// Failed to parse or validate an Alcohol 120% MDS file.
    InvalidMds(String),
    /// Failed to parse or validate a Nero Burning ROM NRG file.
    InvalidNrg(String),
    /// Invalid disc or track metadata in CHD container.
    InvalidMetadata(String),
    /// An unsupported disc track type was encountered.
    UnsupportedTrackType(String),
    /// Attempted to extract to CloneCD format from a CHD lacking raw subchannel data.
    MissingSubcodeForCloneCd,
    /// A sector size mismatch occurred.
    SectorSizeMismatch {
        /// Expected sector size in bytes.
        expected: usize,
        /// Actual sector size found in bytes.
        found: usize,
    },
}

impl fmt::Display for DiscError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Io(e) => write!(f, "I/O error: {}", e),
            Self::Chd(e) => write!(f, "CHD error: {}", e),
            Self::Hound(e) => write!(f, "WAV error: {}", e),
            Self::InvalidCue(msg) => write!(f, "invalid CUE: {}", msg),
            Self::InvalidGdi(msg) => write!(f, "invalid GDI: {}", msg),
            Self::InvalidToc(msg) => write!(f, "invalid TOC: {}", msg),
            Self::InvalidCcd(msg) => write!(f, "invalid CCD: {}", msg),
            Self::InvalidMds(msg) => write!(f, "invalid MDS: {}", msg),
            Self::InvalidNrg(msg) => write!(f, "invalid NRG: {}", msg),
            Self::InvalidMetadata(msg) => write!(f, "invalid disc metadata: {}", msg),
            Self::UnsupportedTrackType(t) => write!(f, "unsupported track type: {}", t),
            Self::MissingSubcodeForCloneCd => write!(
                f,
                "cannot extract to CloneCD (.ccd/.img/.sub): the CHD container does not contain raw subchannel data (SUBTYPE: NONE); consider extracting to CUE/BIN format (.cue) instead"
            ),
            Self::SectorSizeMismatch { expected, found } => {
                write!(
                    f,
                    "sector size mismatch: expected {} bytes, found {} bytes",
                    expected, found
                )
            }
        }
    }
}

impl std::error::Error for DiscError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Self::Io(e) => Some(e),
            Self::Chd(e) => Some(e),
            Self::Hound(e) => Some(e),
            _ => None,
        }
    }
}

impl From<io::Error> for DiscError {
    fn from(err: io::Error) -> Self {
        Self::Io(err)
    }
}

impl From<ChdError> for DiscError {
    fn from(err: ChdError) -> Self {
        Self::Chd(err)
    }
}

impl From<hound::Error> for DiscError {
    fn from(err: hound::Error) -> Self {
        Self::Hound(err)
    }
}