//! Error handling for RTX Vision Advanced use thiserror::Error; /// Result type for vision operations pub type VisionResult = Result; /// Vision-specific error types #[derive(Error, Debug)] pub enum VisionError { /// Tensor operation errors #[error("Tensor operation failed: {message}")] TensorError { message: String, source: Option>, }, /// Model loading errors #[error("Failed to load model: {model_name}")] ModelLoadError { model_name: String, source: Option>, }, /// Invalid model configuration #[error("Invalid model configuration: {reason}")] InvalidConfig { reason: String }, /// Input validation errors #[error("Invalid input: {message}")] InvalidInput { message: String }, /// Image processing errors #[error("Image processing failed: {operation}")] ImageProcessingError { operation: String, source: Option>, }, /// DICOM processing errors (medical imaging) #[error("DICOM processing failed: {message}")] DicomError { message: String, source: Option>, }, /// Point cloud processing errors (autonomous) #[error("Point cloud processing failed: {operation}")] PointCloudError { operation: String, source: Option>, }, /// Detection-specific errors #[error("Detection failed: {detector}, reason: {reason}")] DetectionError { detector: String, reason: String }, /// Segmentation-specific errors #[error("Segmentation failed: {segmenter}, reason: {reason}")] SegmentationError { segmenter: String, reason: String }, /// Tracking errors #[error("Tracking failed: {tracker}, reason: {reason}")] TrackingError { tracker: String, reason: String }, /// GPU/device errors #[error("Device error: {message}")] DeviceError { message: String }, /// Memory allocation errors #[error("Memory allocation failed: {requested_size} bytes")] OutOfMemoryError { requested_size: usize }, /// Model inference errors #[error("Inference failed for model {model_name}: {reason}")] InferenceError { model_name: String, reason: String }, /// Performance optimization errors #[error("Optimization failed: {technique}, reason: {reason}")] OptimizationError { technique: String, reason: String }, /// Feature extraction errors #[error("Feature extraction failed: {extractor}")] FeatureExtractionError { extractor: String }, /// Model quantization errors #[error("Quantization failed: {method}")] QuantizationError { method: String }, /// Network/download errors #[error("Network operation failed: {operation}")] NetworkError { operation: String, source: Option>, }, /// File I/O errors #[error("File I/O error: {path}")] IoError { path: String, source: Option>, }, /// Serialization/deserialization errors #[error("Serialization error: {format}")] SerializationError { format: String, source: Option>, }, /// Generic error for unexpected failures #[error("Unexpected error: {message}")] UnexpectedError { message: String }, } impl VisionError { /// Create a tensor error pub fn tensor_error(message: impl Into) -> Self { Self::TensorError { message: message.into(), source: None, } } /// Create a tensor error with source pub fn tensor_error_with_source( message: impl Into, source: impl std::error::Error + Send + Sync + 'static, ) -> Self { Self::TensorError { message: message.into(), source: Some(Box::new(source)), } } /// Create a model loading error pub fn model_load_error(model_name: impl Into) -> Self { Self::ModelLoadError { model_name: model_name.into(), source: None, } } /// Create an invalid configuration error pub fn invalid_config(reason: impl Into) -> Self { Self::InvalidConfig { reason: reason.into(), } } /// Create an invalid input error pub fn invalid_input(message: impl Into) -> Self { Self::InvalidInput { message: message.into(), } } /// Create a detection error pub fn detection_error(detector: impl Into, reason: impl Into) -> Self { Self::DetectionError { detector: detector.into(), reason: reason.into(), } } /// Create a segmentation error pub fn segmentation_error(segmenter: impl Into, reason: impl Into) -> Self { Self::SegmentationError { segmenter: segmenter.into(), reason: reason.into(), } } /// Create an out of memory error pub fn out_of_memory(requested_size: usize) -> Self { Self::OutOfMemoryError { requested_size } } /// Create an inference error pub fn inference_error(model_name: impl Into, reason: impl Into) -> Self { Self::InferenceError { model_name: model_name.into(), reason: reason.into(), } } /// Create a device error pub fn device_error(message: impl Into) -> Self { Self::DeviceError { message: message.into(), } } } // Convert from common error types impl From for VisionError { fn from(err: anyhow::Error) -> Self { Self::UnexpectedError { message: err.to_string(), } } } impl From for VisionError { fn from(err: rtx_tensor::TensorError) -> Self { Self::TensorError { message: err.to_string(), source: None, } } } impl From for VisionError { fn from(err: std::io::Error) -> Self { Self::IoError { path: "unknown".to_string(), source: Some(Box::new(err)), } } } impl From for VisionError { fn from(err: serde_json::Error) -> Self { Self::SerializationError { format: "JSON".to_string(), source: Some(Box::new(err)), } } } impl From for VisionError { fn from(err: bincode::Error) -> Self { Self::SerializationError { format: "bincode".to_string(), source: Some(Box::new(err)), } } } #[cfg(feature = "opencv")] impl From for VisionError { fn from(err: opencv::Error) -> Self { Self::ImageProcessingError { operation: "OpenCV operation".to_string(), source: Some(Box::new(err)), } } } #[cfg(feature = "medical")] impl From for VisionError { fn from(err: dicom::Error) -> Self { Self::DicomError { message: err.to_string(), source: Some(Box::new(err)), } } } /// Helper macro for creating vision errors #[macro_export] macro_rules! vision_error { ($variant:ident, $($arg:expr),*) => { $crate::error::VisionError::$variant { $($arg),* } }; } /// Helper macro for creating vision results #[macro_export] macro_rules! vision_bail { ($($tokens:tt)*) => { return Err($crate::vision_error!($($tokens)*)) }; } #[cfg(test)] mod tests { use super::*; #[test] fn test_error_creation() { let err = VisionError::tensor_error("test error"); assert!(matches!(err, VisionError::TensorError { .. })); } #[test] fn test_error_display() { let err = VisionError::detection_error("YOLO", "invalid input shape"); let error_str = err.to_string(); assert!(error_str.contains("Detection failed")); assert!(error_str.contains("YOLO")); assert!(error_str.contains("invalid input shape")); } #[test] fn test_error_conversion() { let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found"); let vision_err = VisionError::from(io_err); assert!(matches!(vision_err, VisionError::IoError { .. })); } }