1use std::{error::Error as StdError, fmt, path::PathBuf};
2
3pub type BoxedError = Box<dyn StdError + Send + Sync + 'static>;
6
7pub type Result<T> = std::result::Result<T, Error>;
9
10impl fmt::Debug for Error {
11 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12 write!(f, "{self}")
13 }
14}
15
16#[derive(Debug)]
18pub enum DType {
19 F32,
21 Usize,
23 Other(String),
25}
26
27#[derive(Debug)]
29pub struct ValueWithDtype {
30 pub r#type: DType,
32 pub value: String,
34}
35
36#[derive(Debug, thiserror::Error)]
38pub enum InvalidParameterError {
39 #[error("invalid value for `{name}`: expected {expected}, got {value}")]
41 InvalidValue {
42 name: String,
44 expected: String,
46 value: String,
48 },
49 #[error("value {current_value:?} is outside the range {min:?}..={max:?}")]
51 InvalidRange {
52 min: ValueWithDtype,
54 max: ValueWithDtype,
56 current_value: ValueWithDtype,
58 },
59 #[error("invalid path: {path}", path = .path.display())]
61 InvalidPath {
62 path: PathBuf,
64 },
65}
66
67#[derive(Debug, thiserror::Error)]
69pub enum BrokenArtifact {
70 #[error("missing {artifact_type} artifact at {path}", path = .path.display())]
72 Missing {
73 path: PathBuf,
75 artifact_type: String,
77 },
78 #[error("failed to decode {artifact_type} artifact at {path}: {source}", path = .path.display())]
80 Decode {
81 path: PathBuf,
83 artifact_type: String,
85 #[source]
87 source: BoxedError,
88 },
89}
90
91#[derive(Debug)]
93pub struct BrokenArtifacts {
94 pub broken: Vec<BrokenArtifact>,
96}
97
98impl fmt::Display for BrokenArtifacts {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 for (index, artifact) in self.broken.iter().enumerate() {
101 if index > 0 {
102 f.write_str("; ")?;
103 }
104 write!(f, "{artifact}")?;
105 }
106 Ok(())
107 }
108}
109
110impl StdError for BrokenArtifacts {
111 fn source(&self) -> Option<&(dyn StdError + 'static)> {
112 self.broken
113 .first()
114 .map(|artifact| artifact as &(dyn StdError + 'static))
115 }
116}
117
118impl From<BrokenArtifact> for Error {
119 fn from(artifact: BrokenArtifact) -> Self {
120 Self::BrokenArtifacts(BrokenArtifacts {
121 broken: vec![artifact],
122 })
123 }
124}
125
126#[derive(Debug, thiserror::Error)]
128#[error("missing {dependency_type} dependency `{name}`")]
129pub struct MissingDependency {
130 pub name: String,
132 pub dependency_type: String,
134}
135
136#[derive(Debug, thiserror::Error)]
138#[error("environment operation `{operation}` failed: {source}")]
139pub struct EnvironmentError {
140 pub operation: String,
142 #[source]
144 pub source: BoxedError,
145}
146
147#[derive(Debug, thiserror::Error)]
149pub enum TensorError {
150 #[error("shape mismatch for tensor operation `{operation}`: left {left:?}, right {right:?}")]
152 ShapeMismatch {
153 operation: String,
155 left: Vec<usize>,
157 right: Vec<usize>,
159 },
160 #[error("invalid tensor shape {shape:?}: expected {expected} values, got {actual}")]
162 InvalidShape {
163 shape: Vec<usize>,
165 expected: usize,
167 actual: usize,
169 },
170 #[error("tensor operation `{operation}` requires non-empty input")]
172 EmptyInput {
173 operation: String,
175 },
176 #[error("tensor operation `{operation}` failed: {source}")]
178 Operation {
179 operation: String,
181 #[source]
183 source: BoxedError,
184 },
185}
186
187impl TensorError {
188 pub fn operation(
190 operation: impl Into<String>,
191 source: impl StdError + Send + Sync + 'static,
192 ) -> Self {
193 Self::Operation {
194 operation: operation.into(),
195 source: Box::new(source),
196 }
197 }
198}
199
200#[derive(Debug, thiserror::Error)]
202#[error("{resource} was interrupted: {details}")]
203pub struct ResourceInterrupted {
204 pub resource: String,
206 pub details: String,
208}
209
210#[derive(thiserror::Error)]
212pub enum Error {
213 #[error("invalid parameter: {0}")]
215 InvalidParameter(#[source] Box<InvalidParameterError>),
216
217 #[error("invalid state for `{operation}`: {details}")]
219 InvalidState {
220 operation: String,
222 details: String,
224 },
225
226 #[error("unsupported operation `{operation}`: {details}")]
228 Unsupported {
229 operation: String,
231 details: String,
233 },
234
235 #[error("broken artifacts: {0}")]
237 BrokenArtifacts(#[source] BrokenArtifacts),
238
239 #[error(transparent)]
241 MissingDependency(#[from] MissingDependency),
242
243 #[error(transparent)]
245 Environment(#[from] EnvironmentError),
246
247 #[error(transparent)]
249 Tensor(#[from] TensorError),
250
251 #[error(transparent)]
253 ResourceInterrupted(#[from] ResourceInterrupted),
254
255 #[error(transparent)]
257 Wrapped(#[from] BoxedError),
258}
259
260impl Error {
261 pub fn wrap(error: impl StdError + Send + Sync + 'static) -> Self {
263 Self::Wrapped(Box::new(error))
264 }
265}