gestura_core_foundation/
error.rs1use thiserror::Error;
7
8#[derive(Debug, Error)]
13pub enum AppError {
14 #[error("I/O error: {0}")]
16 Io(#[from] std::io::Error),
17
18 #[error("JSON error: {0}")]
20 Json(#[from] serde_json::Error),
21
22 #[error("TOML error: {0}")]
24 Toml(String),
25
26 #[error("NATS error: {0}")]
28 Nats(String),
29
30 #[error("BLE error: {0}")]
32 Ble(String),
33
34 #[error("LLM error: {0}")]
36 Llm(String),
37
38 #[error("Context overflow: {0}")]
43 ContextOverflow(String),
44
45 #[error("HTTP error: {0}")]
47 Http(#[from] reqwest::Error),
48
49 #[error("Voice error: {0}")]
51 Voice(String),
52
53 #[error("Audio error: {0}")]
55 Audio(String),
56
57 #[error("Config error: {0}")]
59 Config(String),
60
61 #[error("Session error: {0}")]
63 Session(String),
64
65 #[error("MCP error: {0}")]
67 Mcp(String),
68
69 #[error("Permission denied: {0}")]
71 PermissionDenied(String),
72
73 #[error("Not found: {0}")]
75 NotFound(String),
76
77 #[error("Timeout: {0}")]
79 Timeout(String),
80
81 #[error("Invalid input: {0}")]
83 InvalidInput(String),
84
85 #[error("Internal error: {0}")]
87 Internal(String),
88}
89
90pub type Result<T> = std::result::Result<T, AppError>;
92
93impl From<toml::de::Error> for AppError {
95 fn from(err: toml::de::Error) -> Self {
96 AppError::Toml(err.to_string())
97 }
98}
99
100impl From<toml::ser::Error> for AppError {
102 fn from(err: toml::ser::Error) -> Self {
103 AppError::Toml(err.to_string())
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn test_io_error_conversion() {
113 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
114 let app_err: AppError = io_err.into();
115 assert!(matches!(app_err, AppError::Io(_)));
116 assert!(app_err.to_string().contains("file not found"));
117 }
118
119 #[test]
120 fn test_llm_error() {
121 let err = AppError::Llm("API rate limit exceeded".to_string());
122 assert!(err.to_string().contains("API rate limit exceeded"));
123 }
124
125 #[test]
126 fn test_config_error() {
127 let err = AppError::Config("Missing API key".to_string());
128 assert!(err.to_string().contains("Missing API key"));
129 }
130
131 #[test]
132 fn test_result_type_alias() {
133 fn fallible_operation() -> Result<i32> {
134 Ok(42)
135 }
136 assert_eq!(fallible_operation().unwrap(), 42);
137 }
138}