use std::fmt;
use crate::types::ErrCode;
#[derive(Debug, Clone, PartialEq)]
pub enum LepccError {
Failed(String),
WrongParam(String),
WrongVersion {
found: u16,
expected: u16,
},
WrongChecksum {
expected: u32,
found: u32,
},
NotLepcc(String),
NotClusterRgb(String),
NotIntensity(String),
NotFlagBytes(String),
BufferTooSmall {
needed: usize,
provided: usize,
},
OutArrayTooSmall {
needed: usize,
provided: usize,
},
QuantizeVirtualRasterTooBig,
QuantizeIndexOutOfRange {
index: i64,
limit: usize,
},
IoError(String),
}
impl fmt::Display for LepccError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
LepccError::Failed(msg) => write!(f, "Failed: {}", msg),
LepccError::WrongParam(msg) => write!(f, "Wrong Parameter: {}", msg),
LepccError::WrongVersion { found, expected } => {
write!(f, "Wrong Version: found {}, expected {}", found, expected)
}
LepccError::WrongChecksum { expected, found } => {
write!(f, "Wrong Checksum: expected 0x{:08x}, found 0x{:08x}", expected, found)
}
LepccError::NotLepcc(msg) => write!(f, "Not Lepcc: {}", msg),
LepccError::NotClusterRgb(msg) => write!(f, "Not ClusterRgb: {}", msg),
LepccError::NotIntensity(msg) => write!(f, "Not Intensity: {}", msg),
LepccError::NotFlagBytes(msg) => write!(f, "Not FlagBytes: {}", msg),
LepccError::BufferTooSmall { needed, provided } => {
write!(f, "Buffer Too Small: needed {} bytes, provided {} bytes", needed, provided)
}
LepccError::OutArrayTooSmall { needed, provided } => {
write!(f, "Output Array Too Small: needed {} elements, provided {}", needed, provided)
}
LepccError::QuantizeVirtualRasterTooBig => {
write!(f, "Quantize Virtual Raster Too Big")
}
LepccError::QuantizeIndexOutOfRange { index, limit } => {
write!(f, "Quantize Index Out Of Range: index {}, limit {}", index, limit)
}
LepccError::IoError(msg) => write!(f, "I/O Error: {}", msg),
}
}
}
impl std::error::Error for LepccError {}
impl From<ErrCode> for LepccError {
fn from(code: ErrCode) -> Self {
match code {
ErrCode::Ok => unreachable!("Ok should not be converted to error"),
ErrCode::Failed => LepccError::Failed("Operation failed".to_string()),
ErrCode::WrongParam => LepccError::WrongParam("Invalid parameter".to_string()),
ErrCode::WrongVersion => LepccError::WrongVersion { found: 0, expected: 1 },
ErrCode::WrongChecksum => LepccError::WrongChecksum { expected: 0, found: 0 },
ErrCode::NotLepcc => LepccError::NotLepcc("Invalid magic bytes".to_string()),
ErrCode::NotClusterRgb => LepccError::NotClusterRgb("Not ClusterRGB data".to_string()),
ErrCode::NotIntensity => LepccError::NotIntensity("Not Intensity data".to_string()),
ErrCode::NotFlagBytes => LepccError::NotFlagBytes("Not FlagBytes data".to_string()),
ErrCode::BufferTooSmall => LepccError::BufferTooSmall { needed: 0, provided: 0 },
ErrCode::OutArrayTooSmall => LepccError::OutArrayTooSmall { needed: 0, provided: 0 },
ErrCode::QuantizeVirtualRasterTooBig => LepccError::QuantizeVirtualRasterTooBig,
ErrCode::QuantizeIndexOutOfRange => LepccError::QuantizeIndexOutOfRange {
index: 0,
limit: 0,
},
}
}
}
impl From<std::io::Error> for LepccError {
fn from(err: std::io::Error) -> Self {
LepccError::IoError(err.to_string())
}
}
impl std::convert::TryFrom<LepccError> for ErrCode {
type Error = ();
fn try_from(error: LepccError) -> std::result::Result<Self, Self::Error> {
match error {
LepccError::Failed(_) => Ok(ErrCode::Failed),
LepccError::WrongParam(_) => Ok(ErrCode::WrongParam),
LepccError::WrongVersion { .. } => Ok(ErrCode::WrongVersion),
LepccError::WrongChecksum { .. } => Ok(ErrCode::WrongChecksum),
LepccError::NotLepcc(_) => Ok(ErrCode::NotLepcc),
LepccError::NotClusterRgb(_) => Ok(ErrCode::NotClusterRgb),
LepccError::NotIntensity(_) => Ok(ErrCode::NotIntensity),
LepccError::NotFlagBytes(_) => Ok(ErrCode::NotFlagBytes),
LepccError::BufferTooSmall { .. } => Ok(ErrCode::BufferTooSmall),
LepccError::OutArrayTooSmall { .. } => Ok(ErrCode::OutArrayTooSmall),
LepccError::QuantizeVirtualRasterTooBig => Ok(ErrCode::QuantizeVirtualRasterTooBig),
LepccError::QuantizeIndexOutOfRange { .. } => Ok(ErrCode::QuantizeIndexOutOfRange),
LepccError::IoError(_) => Err(()),
}
}
}
pub type Result<T> = std::result::Result<T, LepccError>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = LepccError::WrongParam("test message".to_string());
assert_eq!(format!("{}", err), "Wrong Parameter: test message");
}
#[test]
fn test_error_conversion_from_errcode() {
let err = LepccError::from(ErrCode::WrongParam);
assert!(matches!(err, LepccError::WrongParam(_)));
}
}