302 lines
8.4 KiB
Rust
302 lines
8.4 KiB
Rust
//! Error handling for RTX Vision Advanced
|
|
|
|
use thiserror::Error;
|
|
|
|
/// Result type for vision operations
|
|
pub type VisionResult<T> = Result<T, VisionError>;
|
|
|
|
/// Vision-specific error types
|
|
#[derive(Error, Debug)]
|
|
pub enum VisionError {
|
|
/// Tensor operation errors
|
|
#[error("Tensor operation failed: {message}")]
|
|
TensorError {
|
|
message: String,
|
|
source: Option<Box<dyn std::error::Error + Send + Sync>>,
|
|
},
|
|
|
|
/// Model loading errors
|
|
#[error("Failed to load model: {model_name}")]
|
|
ModelLoadError {
|
|
model_name: String,
|
|
source: Option<Box<dyn std::error::Error + Send + Sync>>,
|
|
},
|
|
|
|
/// 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<Box<dyn std::error::Error + Send + Sync>>,
|
|
},
|
|
|
|
/// DICOM processing errors (medical imaging)
|
|
#[error("DICOM processing failed: {message}")]
|
|
DicomError {
|
|
message: String,
|
|
source: Option<Box<dyn std::error::Error + Send + Sync>>,
|
|
},
|
|
|
|
/// Point cloud processing errors (autonomous)
|
|
#[error("Point cloud processing failed: {operation}")]
|
|
PointCloudError {
|
|
operation: String,
|
|
source: Option<Box<dyn std::error::Error + Send + Sync>>,
|
|
},
|
|
|
|
/// 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<Box<dyn std::error::Error + Send + Sync>>,
|
|
},
|
|
|
|
/// File I/O errors
|
|
#[error("File I/O error: {path}")]
|
|
IoError {
|
|
path: String,
|
|
source: Option<Box<dyn std::error::Error + Send + Sync>>,
|
|
},
|
|
|
|
/// Serialization/deserialization errors
|
|
#[error("Serialization error: {format}")]
|
|
SerializationError {
|
|
format: String,
|
|
source: Option<Box<dyn std::error::Error + Send + Sync>>,
|
|
},
|
|
|
|
/// 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<String>) -> Self {
|
|
Self::TensorError {
|
|
message: message.into(),
|
|
source: None,
|
|
}
|
|
}
|
|
|
|
/// Create a tensor error with source
|
|
pub fn tensor_error_with_source(
|
|
message: impl Into<String>,
|
|
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<String>) -> Self {
|
|
Self::ModelLoadError {
|
|
model_name: model_name.into(),
|
|
source: None,
|
|
}
|
|
}
|
|
|
|
/// Create an invalid configuration error
|
|
pub fn invalid_config(reason: impl Into<String>) -> Self {
|
|
Self::InvalidConfig {
|
|
reason: reason.into(),
|
|
}
|
|
}
|
|
|
|
/// Create an invalid input error
|
|
pub fn invalid_input(message: impl Into<String>) -> Self {
|
|
Self::InvalidInput {
|
|
message: message.into(),
|
|
}
|
|
}
|
|
|
|
/// Create a detection error
|
|
pub fn detection_error(detector: impl Into<String>, reason: impl Into<String>) -> Self {
|
|
Self::DetectionError {
|
|
detector: detector.into(),
|
|
reason: reason.into(),
|
|
}
|
|
}
|
|
|
|
/// Create a segmentation error
|
|
pub fn segmentation_error(segmenter: impl Into<String>, reason: impl Into<String>) -> 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<String>, reason: impl Into<String>) -> Self {
|
|
Self::InferenceError {
|
|
model_name: model_name.into(),
|
|
reason: reason.into(),
|
|
}
|
|
}
|
|
|
|
/// Create a device error
|
|
pub fn device_error(message: impl Into<String>) -> Self {
|
|
Self::DeviceError {
|
|
message: message.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
// Convert from common error types
|
|
impl From<anyhow::Error> for VisionError {
|
|
fn from(err: anyhow::Error) -> Self {
|
|
Self::UnexpectedError {
|
|
message: err.to_string(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<rtx_tensor::TensorError> for VisionError {
|
|
fn from(err: rtx_tensor::TensorError) -> Self {
|
|
Self::TensorError {
|
|
message: err.to_string(),
|
|
source: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<std::io::Error> for VisionError {
|
|
fn from(err: std::io::Error) -> Self {
|
|
Self::IoError {
|
|
path: "unknown".to_string(),
|
|
source: Some(Box::new(err)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<serde_json::Error> for VisionError {
|
|
fn from(err: serde_json::Error) -> Self {
|
|
Self::SerializationError {
|
|
format: "JSON".to_string(),
|
|
source: Some(Box::new(err)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<bincode::Error> for VisionError {
|
|
fn from(err: bincode::Error) -> Self {
|
|
Self::SerializationError {
|
|
format: "bincode".to_string(),
|
|
source: Some(Box::new(err)),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "opencv")]
|
|
impl From<opencv::Error> 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<dicom::Error> 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 { .. }));
|
|
}
|
|
}
|