1use core::fmt;
8
9#[cfg(feature = "std")]
10use std::error::Error;
11
12use crate::types::EdgeIndex;
13
14#[non_exhaustive]
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum QueueError {
20 AtOrAboveHardCap,
22 Backpressured,
24 Empty,
26 Unsupported,
28 Poisoned,
30}
31
32impl fmt::Display for QueueError {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 match self {
35 QueueError::AtOrAboveHardCap => {
36 f.write_str("queue is at or above the hard watermark capacity")
37 }
38 QueueError::Backpressured => {
39 f.write_str("queue is backpressured but not full; caller may retry later")
40 }
41 QueueError::Empty => f.write_str("queue is empty"),
42 QueueError::Unsupported => f.write_str("operation unsupported by this queue/backend"),
43 QueueError::Poisoned => f.write_str("queue lock is poisoned"),
44 }
45 }
46}
47
48#[cfg(feature = "std")]
49impl Error for QueueError {}
50
51#[non_exhaustive]
55#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56pub enum NodeErrorKind {
57 NoInput,
59 Backpressured,
61 OverBudget,
63 ExternalUnavailable,
65 ExecutionFailed,
67}
68
69impl fmt::Display for NodeErrorKind {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 match self {
72 NodeErrorKind::NoInput => {
73 f.write_str("inputs were not available to progress this node")
74 }
75 NodeErrorKind::Backpressured => {
76 f.write_str("outputs could not be enqueued due to backpressure")
77 }
78 NodeErrorKind::OverBudget => {
79 f.write_str("an execution budget or deadline was exceeded")
80 }
81 NodeErrorKind::ExternalUnavailable => {
82 f.write_str("an external dependency was unavailable or timed out")
83 }
84 NodeErrorKind::ExecutionFailed => {
85 f.write_str("a generic failure occurred in node logic")
86 }
87 }
88 }
89}
90
91#[non_exhaustive]
93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
94pub struct NodeError {
95 kind: NodeErrorKind,
97 code: u32,
99}
100
101impl NodeError {
102 pub const fn new(kind: NodeErrorKind, code: u32) -> Self {
104 Self { kind, code }
105 }
106}
107
108impl fmt::Display for NodeError {
109 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110 write!(f, "node error: {} (code: {})", self.kind, self.code)
111 }
112}
113
114#[cfg(feature = "std")]
115impl Error for NodeError {}
116
117impl NodeError {
118 #[inline]
120 pub const fn no_input() -> Self {
121 Self::new(NodeErrorKind::NoInput, 0)
122 }
123 #[inline]
125 pub const fn backpressured() -> Self {
126 Self::new(NodeErrorKind::Backpressured, 0)
127 }
128 #[inline]
130 pub const fn over_budget() -> Self {
131 Self::new(NodeErrorKind::OverBudget, 0)
132 }
133 #[inline]
135 pub const fn external_unavailable() -> Self {
136 Self::new(NodeErrorKind::ExternalUnavailable, 0)
137 }
138 #[inline]
140 pub const fn execution_failed() -> Self {
141 Self::new(NodeErrorKind::ExecutionFailed, 0)
142 }
143
144 #[inline]
146 pub const fn with_code(mut self, code: u32) -> Self {
147 self.code = code;
148 self
149 }
150
151 #[inline]
153 pub const fn kind(&self) -> &NodeErrorKind {
154 &self.kind
155 }
156
157 #[inline]
159 pub const fn code(&self) -> &u32 {
160 &self.code
161 }
162}
163
164impl From<NodeErrorKind> for NodeError {
165 #[inline]
166 fn from(kind: NodeErrorKind) -> Self {
167 NodeError::new(kind, 0)
168 }
169}
170
171#[non_exhaustive]
173#[derive(Debug, Clone, Copy, PartialEq, Eq)]
174pub enum InferenceErrorKind {
175 InvalidArtifact,
177 ShapeOrTypeMismatch,
179 ExecutionFailed,
181 ResourceUnavailable,
183}
184
185impl fmt::Display for InferenceErrorKind {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 match self {
188 InferenceErrorKind::InvalidArtifact => {
189 f.write_str("model artifact is invalid or unsupported")
190 }
191 InferenceErrorKind::ShapeOrTypeMismatch => {
192 f.write_str("input or output payload is incompatible with the model")
193 }
194 InferenceErrorKind::ExecutionFailed => {
195 f.write_str("execution failed inside the backend")
196 }
197 InferenceErrorKind::ResourceUnavailable => {
198 f.write_str("backend resource is unavailable")
199 }
200 }
201 }
202}
203
204#[non_exhaustive]
206#[derive(Debug, Clone, Copy, PartialEq, Eq)]
207pub struct InferenceError {
208 kind: InferenceErrorKind,
210 code: u32,
212}
213
214impl InferenceError {
215 pub const fn new(kind: InferenceErrorKind, code: u32) -> Self {
217 Self { kind, code }
218 }
219
220 #[inline]
222 pub const fn kind(&self) -> &InferenceErrorKind {
223 &self.kind
224 }
225
226 #[inline]
228 pub const fn code(&self) -> &u32 {
229 &self.code
230 }
231}
232
233impl fmt::Display for InferenceError {
234 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
235 write!(f, "inference error: {} (code: {})", self.kind, self.code)
236 }
237}
238
239#[cfg(feature = "std")]
240impl Error for InferenceError {}
241
242#[non_exhaustive]
246#[derive(Debug, Clone, Copy, PartialEq, Eq)]
247pub enum GraphError {
248 Cyclic,
251 IncompatiblePorts,
253 InvalidCapacity,
255 InvalidEdgeIndex,
257 OccupancySampleFailed(EdgeIndex),
259}
260
261impl fmt::Display for GraphError {
262 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
263 match self {
264 GraphError::Cyclic => f.write_str("graph contains a cycle"),
265 GraphError::IncompatiblePorts => {
266 f.write_str("port schema or memory placement is incompatible across an edge")
267 }
268 GraphError::InvalidCapacity => {
269 f.write_str("queue capacity or watermark configuration is invalid")
270 }
271 GraphError::InvalidEdgeIndex => f.write_str("edge index is invalid"),
272 GraphError::OccupancySampleFailed(ei) => {
273 write!(f, "failed to sample occupancy for edge {}", ei.as_usize())
274 }
275 }
276 }
277}
278
279#[cfg(feature = "std")]
280impl Error for GraphError {}
281
282#[non_exhaustive]
286#[derive(Debug, Clone, Copy, PartialEq, Eq)]
287pub enum RuntimeErrorKind {
288 InvariantViolation,
290 PlatformUnavailable,
292 Unsupported,
294 Unknown,
296}
297
298impl fmt::Display for RuntimeErrorKind {
299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300 match self {
301 RuntimeErrorKind::InvariantViolation => f.write_str("an invariant has been violated"),
302 RuntimeErrorKind::PlatformUnavailable => {
303 f.write_str("a requested platform service is unavailable")
304 }
305 RuntimeErrorKind::Unsupported => {
306 f.write_str("the operation is unsupported in this profile or configuration")
307 }
308 RuntimeErrorKind::Unknown => f.write_str("an unspecified failure occurred"),
309 }
310 }
311}
312
313#[cfg(feature = "std")]
314impl Error for RuntimeErrorKind {}
315
316#[non_exhaustive]
318#[derive(Debug, Clone, Copy, PartialEq, Eq)]
319pub enum SchedulerError {
320 InvariantViolation,
322 Internal,
324}
325
326impl fmt::Display for SchedulerError {
327 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
328 match self {
329 SchedulerError::InvariantViolation => {
330 f.write_str("the scheduler cannot proceed due to an invariant violation")
331 }
332 SchedulerError::Internal => f.write_str("an internal scheduler error occurred"),
333 }
334 }
335}
336
337#[cfg(feature = "std")]
338impl Error for SchedulerError {}
339
340#[non_exhaustive]
344#[derive(Debug, Clone, Copy, PartialEq, Eq)]
345pub enum SensorError {
346 OpenFailed,
348 ReadFailed,
350 EndOfStream,
352 ResetFailed,
354 ConfigurationInvalid,
356}
357
358impl fmt::Display for SensorError {
359 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
360 match self {
361 SensorError::OpenFailed => f.write_str("sensor open failed"),
362 SensorError::ReadFailed => f.write_str("sensor read failed"),
363 SensorError::EndOfStream => f.write_str("sensor stream ended"),
364 SensorError::ResetFailed => f.write_str("sensor reset failed"),
365 SensorError::ConfigurationInvalid => f.write_str("invalid sensor configuration"),
366 }
367 }
368}
369
370#[cfg(feature = "std")]
371impl Error for SensorError {}
372
373#[non_exhaustive]
377#[derive(Debug, Clone, Copy, PartialEq, Eq)]
378pub enum OutputError {
379 WriteFailed,
381 FlushFailed,
383}
384
385impl fmt::Display for OutputError {
386 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
387 match self {
388 OutputError::WriteFailed => f.write_str("sink write failed"),
389 OutputError::FlushFailed => f.write_str("sink flush failed"),
390 }
391 }
392}
393
394#[cfg(feature = "std")]
395impl Error for OutputError {}
396
397#[non_exhaustive]
401#[derive(Debug, Clone, Copy, PartialEq, Eq)]
402pub enum MemoryError {
403 NoFreeSlots,
405 BadToken,
407 NotAllocated,
409 AlreadyBorrowed,
412 BorrowActive,
414 Poisoned,
416}
417
418impl fmt::Display for MemoryError {
419 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
420 match self {
421 MemoryError::NoFreeSlots => f.write_str("no free slots in memory manager"),
422 MemoryError::BadToken => f.write_str("token index out of range or slot not allocated"),
423 MemoryError::NotAllocated => {
424 f.write_str("attempted to free a slot that is not allocated")
425 }
426 MemoryError::AlreadyBorrowed => f.write_str("slot already borrowed incompatibly"),
427 MemoryError::BorrowActive => f.write_str("cannot free slot while borrows are active"),
428 MemoryError::Poisoned => f.write_str("synchronization primitive is poisoned"),
429 }
430 }
431}
432
433#[cfg(feature = "std")]
434impl Error for MemoryError {}
435
436#[non_exhaustive]
440#[derive(Debug, Clone, Copy, PartialEq, Eq)]
441pub enum RuntimeInvariantError {
442 UninitializedClock,
444 UninitializedTelemetry,
446}
447
448impl fmt::Display for RuntimeInvariantError {
449 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
450 match self {
451 RuntimeInvariantError::UninitializedClock => f.write_str("clock not present"),
452 RuntimeInvariantError::UninitializedTelemetry => f.write_str("telemetry not present"),
453 }
454 }
455}
456
457#[non_exhaustive]
459#[derive(Debug, Clone, Copy, PartialEq, Eq)]
460pub enum RuntimeError {
461 Graph(GraphError),
463 Node(NodeError),
465 RuntimeInvariant(RuntimeInvariantError),
467}
468
469impl From<GraphError> for RuntimeError {
470 #[inline]
471 fn from(e: GraphError) -> Self {
472 RuntimeError::Graph(e)
473 }
474}
475
476impl From<NodeError> for RuntimeError {
477 #[inline]
478 fn from(e: NodeError) -> Self {
479 RuntimeError::Node(e)
480 }
481}
482
483impl From<RuntimeInvariantError> for RuntimeError {
484 #[inline]
485 fn from(e: RuntimeInvariantError) -> Self {
486 RuntimeError::RuntimeInvariant(e)
487 }
488}
489
490impl fmt::Display for RuntimeError {
491 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
492 match self {
493 RuntimeError::Graph(e) => write!(f, "runtime graph error: {e}"),
494 RuntimeError::Node(e) => write!(f, "runtime node error: {e}"),
495 RuntimeError::RuntimeInvariant(e) => write!(f, "runtime invariant error: {e}"),
496 }
497 }
498}
499
500#[cfg(feature = "std")]
501impl std::error::Error for RuntimeError {}