use thiserror::Error;
pub type Result<T> = std::result::Result<T, IffError>;
#[derive(Error, Debug)]
pub enum IffError {
#[error("Invalid magic number: expected 0x{expected:08X}, got 0x{got:08X}")]
InvalidMagic { expected: u32, got: u32 },
#[error("Unsupported version: {0}")]
UnsupportedVersion(u32),
#[error("Image dimension {dimension} exceeds maximum {max}")]
DimensionTooLarge { dimension: u32, max: u32 },
#[error("Invalid wavelet coefficient at ({x}, {y}, {level})")]
InvalidWaveletCoefficient { x: usize, y: usize, level: usize },
#[error("Invalid region: position ({x}, {y}), size ({w}, {h})")]
InvalidRegion {
x: u16,
y: u16,
w: u16,
h: u16,
},
#[error("Invalid vortex at position ({x}, {y})")]
InvalidVortex { x: u16, y: u16 },
#[error("Fixed-point overflow in operation: {operation}")]
FixedPointOverflow { operation: String },
#[error("Insufficient data: expected {expected} bytes, got {got}")]
InsufficientData { expected: usize, got: usize },
#[error("Corrupted bitstream at offset {offset}: {reason}")]
CorruptedBitstream { offset: usize, reason: String },
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Serialization error: {0}")]
Serialization(String),
#[cfg(feature = "gpu")]
#[error("GPU error: {0}")]
Gpu(String),
#[cfg(feature = "encoder")]
#[error("Encoding error: {0}")]
Encoding(String),
#[cfg(feature = "decoder")]
#[error("Decoding error: {0}")]
Decoding(String),
#[error("{0}")]
Other(String),
}
impl From<bincode::Error> for IffError {
fn from(err: bincode::Error) -> Self {
IffError::Serialization(err.to_string())
}
}
impl From<rmp_serde::encode::Error> for IffError {
fn from(err: rmp_serde::encode::Error) -> Self {
IffError::Serialization(err.to_string())
}
}
impl From<rmp_serde::decode::Error> for IffError {
fn from(err: rmp_serde::decode::Error) -> Self {
IffError::Serialization(err.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = IffError::InvalidMagic {
expected: 0x50504649,
got: 0x12345678,
};
assert!(err.to_string().contains("0x50504649"));
assert!(err.to_string().contains("0x12345678"));
}
#[test]
fn test_dimension_error() {
let err = IffError::DimensionTooLarge {
dimension: 100000,
max: 65536,
};
assert!(err.to_string().contains("100000"));
assert!(err.to_string().contains("65536"));
}
}