Files
rustytorch/crates/models/rtx-vision-advanced/src/error.rs
T
2026-03-04 00:08:42 +00:00

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 { .. }));
}
}