1use super::{ErrorCategory, ErrorContext, ErrorLocation, ErrorSeverity, OperationContext};
7use std::io;
8use thiserror::Error;
9
10#[derive(Error, Debug)]
12pub enum NumRs2Error {
13 #[error("Shape mismatch: expected {expected:?}, got {actual:?}")]
14 ShapeMismatch {
15 expected: Vec<usize>,
16 actual: Vec<usize>,
17 },
18
19 #[error("Dimension mismatch: {0}")]
20 DimensionMismatch(String),
21
22 #[error("Invalid operation: {0}")]
23 InvalidOperation(String),
24
25 #[error("Value error: {0}")]
26 ValueError(String),
27
28 #[error("Index error: {0}")]
29 IndexError(String),
30
31 #[error("BLAS error: code {0}")]
32 BlasError(i32),
33
34 #[error("LAPACK error: {0}")]
35 LapackError(String),
36
37 #[error("Conversion error: {0}")]
38 ConversionError(String),
39
40 #[error("Type cast error: {0}")]
41 TypeCastError(String),
42
43 #[error("Index out of bounds: {0}")]
44 IndexOutOfBounds(String),
45
46 #[error("Computation error: {0}")]
47 ComputationError(String),
48
49 #[error("Serialization error: {0}")]
50 SerializationError(String),
51
52 #[error("Deserialization error: {0}")]
53 DeserializationError(String),
54
55 #[error("I/O error: {0}")]
56 IOError(String),
57
58 #[error("Not implemented: {0}")]
59 NotImplemented(String),
60
61 #[error("Runtime error: {0}")]
62 RuntimeError(String),
63
64 #[error("Memory allocation failed: {0}")]
65 AllocationFailed(String),
66
67 #[error("Feature not enabled: {0}")]
68 FeatureNotEnabled(String),
69
70 #[error("{0}")]
72 Core(#[from] super::hierarchical::CoreError),
73
74 #[error("{0}")]
75 Computation(#[from] super::hierarchical::ComputationError),
76
77 #[error("{0}")]
78 Memory(#[from] super::hierarchical::MemoryError),
79
80 #[error("{0}")]
81 IO(#[from] super::hierarchical::IOError),
82}
83
84pub type Result<T> = std::result::Result<T, NumRs2Error>;
86
87impl From<io::Error> for NumRs2Error {
89 fn from(err: io::Error) -> Self {
90 NumRs2Error::IOError(err.to_string())
91 }
92}
93
94impl From<Box<bincode::ErrorKind>> for NumRs2Error {
96 fn from(err: Box<bincode::ErrorKind>) -> Self {
97 NumRs2Error::DeserializationError(err.to_string())
98 }
99}
100
101impl NumRs2Error {
102 pub fn category(&self) -> ErrorCategory {
104 match self {
105 NumRs2Error::Core(_) => ErrorCategory::Core,
106 NumRs2Error::Computation(_) => ErrorCategory::Computation,
107 NumRs2Error::Memory(_) => ErrorCategory::Memory,
108 NumRs2Error::IO(_) => ErrorCategory::IO,
109
110 NumRs2Error::DimensionMismatch(_)
112 | NumRs2Error::InvalidOperation(_)
113 | NumRs2Error::ValueError(_)
114 | NumRs2Error::IndexError(_)
115 | NumRs2Error::IndexOutOfBounds(_)
116 | NumRs2Error::ConversionError(_)
117 | NumRs2Error::TypeCastError(_)
118 | NumRs2Error::ShapeMismatch { .. } => ErrorCategory::Core,
119
120 NumRs2Error::ComputationError(_)
121 | NumRs2Error::BlasError(_)
122 | NumRs2Error::LapackError(_) => ErrorCategory::Computation,
123
124 NumRs2Error::AllocationFailed(_) => ErrorCategory::Memory,
125
126 NumRs2Error::SerializationError(_)
127 | NumRs2Error::DeserializationError(_)
128 | NumRs2Error::IOError(_) => ErrorCategory::IO,
129
130 NumRs2Error::NotImplemented(_)
131 | NumRs2Error::RuntimeError(_)
132 | NumRs2Error::FeatureNotEnabled(_) => ErrorCategory::Core,
133 }
134 }
135
136 pub fn severity(&self) -> ErrorSeverity {
138 match self {
139 NumRs2Error::Core(e) => e.severity(),
140 NumRs2Error::Computation(e) => e.severity(),
141 NumRs2Error::Memory(e) => e.severity(),
142 NumRs2Error::IO(e) => e.severity(),
143
144 NumRs2Error::AllocationFailed(_) => ErrorSeverity::Critical,
146 NumRs2Error::LapackError(_) | NumRs2Error::BlasError(_) => ErrorSeverity::High,
147 NumRs2Error::DimensionMismatch(_) | NumRs2Error::ShapeMismatch { .. } => {
148 ErrorSeverity::High
149 }
150 NumRs2Error::IndexOutOfBounds(_) | NumRs2Error::IndexError(_) => ErrorSeverity::Medium,
151 NumRs2Error::NotImplemented(_) | NumRs2Error::FeatureNotEnabled(_) => {
152 ErrorSeverity::Low
153 }
154 _ => ErrorSeverity::Medium,
155 }
156 }
157
158 pub fn is_recoverable(&self) -> bool {
160 match self.severity() {
161 ErrorSeverity::Critical => false,
162 ErrorSeverity::High => false,
163 ErrorSeverity::Medium => true,
164 ErrorSeverity::Low => true,
165 }
166 }
167
168 pub fn with_context<C: Into<OperationContext>>(self, context: C) -> ErrorContext<Self> {
170 ErrorContext::new(self, context.into())
171 }
172
173 pub fn at_location(self, location: ErrorLocation) -> ErrorContext<Self> {
175 ErrorContext::new(self, OperationContext::default()).with_location(location)
176 }
177}