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}