//! 分层错误类型:预处理、推理、解码三阶段的强类型错误。 use thiserror::Error; /// 全局统一的 `Result` 别名,默认错误类型为 [`DdddError`]。 pub type Result = std::result::Result; /// 顶层错误类型,聚合本库各阶段错误。 #[derive(Error, Debug)] pub enum DdddError { /// 图像预处理阶段异常。 #[error("图像预处理失败: {0}")] Preprocess(#[from] ImagePreprocessError), /// 推理与张量操作阶段异常。 #[error("推理与模型输入/输出张量异常: {0}")] Inference(#[from] TensorError), /// 后处理解码阶段异常。 #[error("后处理解码错误: {0}")] Decode(#[from] DecodeError), /// 框架内部不可恢复的逻辑断言错误(如解析节点 Fact 失败)。 #[error("内部严重逻辑错误: {0}")] Internal(String), /// 用户自定义扩展错误,用于包装第三方插件产生的错误。 #[error("用户自定义扩展错误: {0}")] Other(#[source] Box), } /// 图像预处理阶段错误类型。 #[derive(Error, Debug)] pub enum ImagePreprocessError { /// ndarray 基础操作失败。 #[error("图片转矩阵(ndarray)基础操作失败: {0}")] Ndarray(#[from] ndarray::ShapeError), /// 图像矩阵维度不合规。 #[error("图像矩阵维度不合规!预期: {expected},实际图像形状: {actual:?}")] InvalidDimensions { /// 期望的维度描述。 expected: String, /// 实际的图像形状。 actual: Vec, }, /// 图像缓冲区长度与分辨率/通道数不匹配。 #[error( "图像缓冲区长度不匹配!预期大小: {expected},实际大小: {actual} (分辨率: {width}x{height}, 通道数: {channels})" )] BufferLengthMismatch { /// 期望的缓冲区长度。 expected: usize, /// 实际的缓冲区长度。 actual: usize, /// 图像宽度。 width: u32, /// 图像高度。 height: u32, /// 图像通道数。 channels: usize, }, /// 不支持的图像通道数。 #[error("不支持的图像通道数: {0} (仅支持单通道灰度L、3通道RGB、4通道RGBA)")] UnsupportedChannels(usize), /// HSV 颜色区间参数非法。 #[error("HSV 颜色区间参数非法: {0}")] InvalidHsvRange(String), /// 未知的颜色预设名称。 #[error("不支持的颜色预设名称: {0}")] UnknownColorPreset(String), /// 颜色过滤器配置无效。 #[error("颜色过滤器配置无效或初始化失败: {0}")] FilterConfigInvalid(String), /// 图像维度不匹配。 #[error("图像维度不匹配!{0}")] MismatchDimensions(String), /// 滑块模板尺寸大于背景图。 #[error("滑块模板尺寸 [{target_w}x{target_h}] 大于背景图 [{bg_w}x{bg_h}]")] TargetExceedsBackground { /// 滑块模板宽度。 target_w: usize, /// 滑块模板高度。 target_h: usize, /// 背景图宽度。 bg_w: usize, /// 背景图高度。 bg_h: usize, }, } /// 推理与张量操作阶段错误类型。 #[derive(Error, Debug)] pub enum TensorError { /// 推理引擎内部异常。 #[error("推理引擎内部发生异常: {0}")] Engine(String), /// 模型张量维度不匹配。 #[error("模型张量维度不匹配!预期: {expected},实际 Tensor 形状: {actual:?}")] DimensionMismatch { /// 期望的维度描述。 expected: String, /// 实际的 Tensor 形状。 actual: Vec, }, /// OCR Logits 矩阵变形失败。 #[error("OCR Logits 矩阵变形失败: {0}")] LogitsDimensionMismatch(#[from] ndarray::ShapeError), /// 张量内存不连续。 #[error("内存不连续,无法执行零拷贝操作")] NonContiguousMemory, /// 未知的模型输出格式。 #[error("未知的模型输出格式")] UnknownOutputFormat, } /// 算法解码阶段错误类型。 #[derive(Error, Debug)] pub enum DecodeError { /// CTC 解码异常。 #[error("CTC 解码异常: {0}")] Ctc(String), } impl DdddError { /// 手动包装任意第三方错误为 [`DdddError::Other`]。 pub fn new(error: E) -> Self where E: Into>, { DdddError::Other(error.into()) } /// 是否为图片维度不合规错误。 pub fn is_invalid_dimensions(&self) -> bool { matches!( self, DdddError::Preprocess(ImagePreprocessError::InvalidDimensions { .. }) ) } /// 是否因通道数不合规而失败。 pub fn is_unsupported_channels(&self) -> bool { matches!( self, DdddError::Preprocess(ImagePreprocessError::UnsupportedChannels(_)) ) } } #[cfg(test)] mod tests { use super::*; #[test] fn new_wraps_third_party_error() { let io_err = std::io::Error::other("boom"); let err = DdddError::new(io_err); assert!(matches!(err, DdddError::Other(_))); } #[test] fn preprocess_conversion_and_predicates() { let e: DdddError = ImagePreprocessError::UnsupportedChannels(2).into(); assert!(e.is_unsupported_channels()); let e2: DdddError = ImagePreprocessError::InvalidDimensions { expected: "x".into(), actual: vec![0], } .into(); assert!(e2.is_invalid_dimensions()); } #[test] fn decode_conversion() { let e: DdddError = DecodeError::Ctc("bad".into()).into(); assert!(matches!(e, DdddError::Decode(_))); } }