edge_impulse_runner/error.rs
1//! Error types for the Edge Impulse Runner.
2//!
3//! This module defines the error types that can occur during model loading,
4//! execution, and communication. It provides a comprehensive error handling
5//! system that helps identify and debug issues when working with Edge Impulse
6//! models.
7//!
8//! The main error type is `EdgeImpulseError`, which encompasses all possible error
9//! conditions that can occur within the library, including both EIM and FFI modes.
10//!
11//! ## Error Types
12//!
13//! - **EdgeImpulseError**: Main error type for inference operations
14//! - **IngestionError**: Error type for data upload operations
15
16use std::error::Error;
17use std::fmt;
18use std::io;
19use thiserror::Error;
20
21/// Represents all possible errors that can occur in the Edge Impulse Runner.
22///
23/// This enum implements the standard Error trait using thiserror and provides
24/// detailed error messages for each error case. It handles both internal errors
25/// and wrapped errors from external dependencies.
26#[derive(Error, Debug)]
27pub enum EdgeImpulseError {
28 /// Indicates a failure in file system operations when accessing the EIM file.
29 ///
30 /// This error occurs when there are problems reading, writing, or accessing
31 /// the model file. It wraps the standard IO error for more details.
32 #[error("Failed to access EIM file: {0}")]
33 FileError(#[from] std::io::Error),
34
35 /// Indicates that the provided path to the EIM file is invalid.
36 ///
37 /// This error occurs when:
38 /// - The path doesn't exist
39 /// - The file extension is not .eim
40 /// - The path points to a directory instead of a file
41 #[error("Invalid EIM file path")]
42 InvalidPath,
43
44 /// Indicates a failure during model execution.
45 ///
46 /// This error occurs when:
47 /// - The model process crashes
48 /// - The model fails to initialize
49 /// - There's an internal model error during inference
50 #[error("Failed to execute EIM model: {0}")]
51 ExecutionError(String),
52
53 /// Indicates a failure in Unix socket communication.
54 ///
55 /// This error occurs when:
56 /// - The socket connection fails
57 /// - Messages can't be sent or received
58 /// - The socket connection is unexpectedly closed
59 #[error("Socket communication error: {0}")]
60 SocketError(String),
61
62 /// Indicates a failure in JSON serialization or deserialization.
63 ///
64 /// This error occurs when:
65 /// - Messages can't be encoded to JSON
66 /// - Responses can't be decoded from JSON
67 /// - The JSON structure doesn't match expected schema
68 #[error("JSON error: {0}")]
69 JsonError(#[from] serde_json::Error),
70
71 /// Indicates that the provided input data is invalid.
72 ///
73 /// This error occurs when:
74 /// - Input features don't match expected dimensions
75 /// - Input values are out of valid ranges
76 /// - Required input parameters are missing
77 #[error("Invalid input: {0}")]
78 InvalidInput(String),
79
80 /// Indicates that an invalid operation was attempted.
81 ///
82 /// This error occurs when:
83 /// - Operations are called in wrong order
84 /// - Unsupported operations are requested
85 /// - Operation parameters are incompatible
86 #[error("Invalid operation: {0}")]
87 InvalidOperation(String),
88}
89
90#[derive(Debug)]
91pub enum IngestionError {
92 Server { status_code: u16, message: String },
93 Config(String),
94 Network(reqwest::Error),
95 Json(serde_json::Error),
96 Header(reqwest::header::InvalidHeaderValue),
97 Io(io::Error),
98}
99
100impl fmt::Display for IngestionError {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 match self {
103 IngestionError::Server {
104 status_code,
105 message,
106 } => {
107 write!(f, "Server error {status_code}: {message}")
108 }
109 IngestionError::Config(msg) => write!(f, "Configuration error: {msg}"),
110 IngestionError::Network(e) => write!(f, "Network error: {e}"),
111 IngestionError::Json(e) => write!(f, "JSON error: {e}"),
112 IngestionError::Header(e) => write!(f, "Header error: {e}"),
113 IngestionError::Io(e) => write!(f, "IO error: {e}"),
114 }
115 }
116}
117
118impl Error for IngestionError {
119 fn source(&self) -> Option<&(dyn Error + 'static)> {
120 match self {
121 IngestionError::Network(e) => Some(e),
122 IngestionError::Json(e) => Some(e),
123 IngestionError::Header(e) => Some(e),
124 IngestionError::Io(e) => Some(e),
125 _ => None,
126 }
127 }
128}
129
130impl From<reqwest::Error> for IngestionError {
131 fn from(err: reqwest::Error) -> Self {
132 IngestionError::Network(err)
133 }
134}
135
136impl From<serde_json::Error> for IngestionError {
137 fn from(err: serde_json::Error) -> Self {
138 IngestionError::Json(err)
139 }
140}
141
142impl From<reqwest::header::InvalidHeaderValue> for IngestionError {
143 fn from(err: reqwest::header::InvalidHeaderValue) -> Self {
144 IngestionError::Header(err)
145 }
146}
147
148impl From<io::Error> for IngestionError {
149 fn from(err: io::Error) -> Self {
150 IngestionError::Io(err)
151 }
152}