1use serde::{Deserialize, Serialize};
4use std::fmt;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
8pub enum ErrorKind {
9 Validation,
11 Network,
13 Storage,
15 Internal,
17 NotFound,
19 Permission,
21 Timeout,
23 Config,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
29pub enum ValidationErrorKind {
30 InvalidFormat {
32 field: String,
34 expected: String,
36 },
37 OutOfRange {
39 field: String,
41 min: Option<String>,
43 max: Option<String>,
45 },
46 Required {
48 field: String,
50 },
51 AlreadyExists {
53 field: String,
55 value: String,
57 },
58 NotAllowed {
60 field: String,
62 allowed: Vec<String>,
64 },
65 CustomValidation {
67 field: String,
69 message: String,
71 },
72}
73
74impl fmt::Display for ValidationErrorKind {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 match self {
77 ValidationErrorKind::InvalidFormat { field, expected } => {
78 write!(f, "invalid_format: field '{}' expected {}", field, expected)
79 }
80 ValidationErrorKind::OutOfRange { field, min, max } => {
81 write!(f, "out_of_range: field '{}'", field)?;
82 if let Some(min) = min {
83 write!(f, " min={}", min)?;
84 }
85 if let Some(max) = max {
86 write!(f, " max={}", max)?;
87 }
88 Ok(())
89 }
90 ValidationErrorKind::Required { field } => write!(f, "required: field '{}' is required", field),
91 ValidationErrorKind::AlreadyExists { field, value } => {
92 write!(f, "already_exists: field '{}' with value '{}' already exists", field, value)
93 }
94 ValidationErrorKind::NotAllowed { field, allowed } => {
95 write!(f, "not_allowed: field '{}' must be one of {:?}", field, allowed)
96 }
97 ValidationErrorKind::CustomValidation { field, message } => {
98 write!(f, "validation_error: field '{}' - {}", field, message)
99 }
100 }
101 }
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
106pub enum NetworkErrorKind {
107 ConnectionFailed,
109 DnsFailed,
111 DnsResolutionFailed,
113 Timeout,
115 TlsError,
117 ProtocolError,
119}
120
121impl fmt::Display for NetworkErrorKind {
122 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123 match self {
124 NetworkErrorKind::ConnectionFailed => write!(f, "connection_failed"),
125 NetworkErrorKind::DnsFailed => write!(f, "dns_failed"),
126 NetworkErrorKind::DnsResolutionFailed => write!(f, "dns_resolution_failed"),
127 NetworkErrorKind::Timeout => write!(f, "timeout"),
128 NetworkErrorKind::TlsError => write!(f, "tls_error"),
129 NetworkErrorKind::ProtocolError => write!(f, "protocol_error"),
130 }
131 }
132}
133
134#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
136pub enum StorageErrorKind {
137 ReadFailed,
139 WriteFailed,
141 DeleteFailed,
143 InsufficientCapacity,
145 DataCorruption,
147 FileNotFound,
149}
150
151impl fmt::Display for StorageErrorKind {
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 match self {
154 StorageErrorKind::ReadFailed => write!(f, "read_failed"),
155 StorageErrorKind::WriteFailed => write!(f, "write_failed"),
156 StorageErrorKind::DeleteFailed => write!(f, "delete_failed"),
157 StorageErrorKind::InsufficientCapacity => write!(f, "insufficient_capacity"),
158 StorageErrorKind::DataCorruption => write!(f, "data_corruption"),
159 StorageErrorKind::FileNotFound => write!(f, "file_not_found"),
160 }
161 }
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize)]
166pub enum DatabaseErrorKind {
167 ConnectionFailed {
169 message: String,
171 },
172 QueryFailed {
174 query: Option<String>,
176 message: String,
178 },
179 ExecuteFailed {
181 query: Option<String>,
183 message: String,
185 },
186 TransactionFailed {
188 message: String,
190 },
191 MigrationFailed {
193 message: String,
195 },
196}
197
198impl fmt::Display for DatabaseErrorKind {
199 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200 match self {
201 DatabaseErrorKind::ConnectionFailed { message } => {
202 write!(f, "connection_failed: {}", message)
203 }
204 DatabaseErrorKind::QueryFailed { query, message } => {
205 if let Some(q) = query {
206 write!(f, "query_failed ({}): {}", q, message)
207 }
208 else {
209 write!(f, "query_failed: {}", message)
210 }
211 }
212 DatabaseErrorKind::ExecuteFailed { query, message } => {
213 if let Some(q) = query {
214 write!(f, "execute_failed ({}): {}", q, message)
215 }
216 else {
217 write!(f, "execute_failed: {}", message)
218 }
219 }
220 DatabaseErrorKind::TransactionFailed { message } => {
221 write!(f, "transaction_failed: {}", message)
222 }
223 DatabaseErrorKind::MigrationFailed { message } => {
224 write!(f, "migration_failed: {}", message)
225 }
226 }
227 }
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize)]
232pub struct WaeError {
233 pub kind: ErrorKind,
235 pub message: Option<String>,
237 pub params: std::collections::HashMap<String, String>,
239}
240
241impl WaeError {
242 pub fn new(kind: ErrorKind) -> Self {
244 Self { kind, message: None, params: std::collections::HashMap::new() }
245 }
246
247 pub fn validation(kind: ValidationErrorKind) -> Self {
249 Self::new(ErrorKind::Validation).with_param("validation_kind", kind.to_string())
250 }
251
252 pub fn validation_message(message: impl Into<String>) -> Self {
254 Self::new(ErrorKind::Validation).with_message(message)
255 }
256
257 pub fn network(kind: NetworkErrorKind) -> Self {
259 Self::new(ErrorKind::Network).with_param("network_kind", kind.to_string())
260 }
261
262 pub fn storage(kind: StorageErrorKind) -> Self {
264 Self::new(ErrorKind::Storage).with_param("storage_kind", kind.to_string())
265 }
266
267 pub fn database(kind: DatabaseErrorKind) -> Self {
269 Self::new(ErrorKind::Internal).with_param("database_kind", kind.to_string())
270 }
271
272 pub fn internal(message: impl Into<String>) -> Self {
274 Self::new(ErrorKind::Internal).with_message(message)
275 }
276
277 pub fn not_found(resource: impl Into<String>) -> Self {
279 Self::new(ErrorKind::NotFound).with_param("resource", resource)
280 }
281
282 pub fn permission(action: impl Into<String>) -> Self {
284 Self::new(ErrorKind::Permission).with_param("action", action)
285 }
286
287 pub fn timeout(operation: impl Into<String>) -> Self {
289 Self::new(ErrorKind::Timeout).with_param("operation", operation)
290 }
291
292 pub fn config(message: impl Into<String>) -> Self {
294 Self::new(ErrorKind::Config).with_message(message)
295 }
296
297 pub fn invalid_params(message: impl Into<String>) -> Self {
299 Self::new(ErrorKind::Validation).with_message(message)
300 }
301
302 pub fn with_message(mut self, message: impl Into<String>) -> Self {
304 self.message = Some(message.into());
305 self
306 }
307
308 pub fn with_param(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
310 self.params.insert(key.into(), value.into());
311 self
312 }
313
314 pub fn get_param(&self, key: &str) -> Option<&String> {
316 self.params.get(key)
317 }
318}
319
320impl fmt::Display for WaeError {
321 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
322 match &self.message {
323 Some(msg) => write!(f, "{:?}: {}", self.kind, msg),
324 None => write!(f, "{:?}", self.kind),
325 }
326 }
327}
328
329impl std::error::Error for WaeError {}
330
331impl From<ValidationErrorKind> for WaeError {
332 fn from(kind: ValidationErrorKind) -> Self {
333 let message = match &kind {
334 ValidationErrorKind::InvalidFormat { field, expected } => {
335 format!("Invalid format for field '{}': expected {}", field, expected)
336 }
337 ValidationErrorKind::OutOfRange { field, min, max } => match (min, max) {
338 (Some(min), Some(max)) => format!("Field '{}' out of range: expected between {} and {}", field, min, max),
339 (Some(min), None) => format!("Field '{}' out of range: expected >= {}", field, min),
340 (None, Some(max)) => format!("Field '{}' out of range: expected <= {}", field, max),
341 (None, None) => format!("Field '{}' out of range", field),
342 },
343 ValidationErrorKind::Required { field } => format!("Field '{}' is required", field),
344 ValidationErrorKind::AlreadyExists { field, value } => {
345 format!("Field '{}' with value '{}' already exists", field, value)
346 }
347 ValidationErrorKind::NotAllowed { field, allowed } => {
348 format!("Field '{}' value not allowed. Allowed values: {:?}", field, allowed)
349 }
350 ValidationErrorKind::CustomValidation { field, message } => {
351 format!("Validation error for field '{}': {}", field, message)
352 }
353 };
354 Self::new(ErrorKind::Validation).with_message(message)
355 }
356}
357
358impl From<NetworkErrorKind> for WaeError {
359 fn from(kind: NetworkErrorKind) -> Self {
360 Self::network(kind)
361 }
362}
363
364impl From<StorageErrorKind> for WaeError {
365 fn from(kind: StorageErrorKind) -> Self {
366 Self::storage(kind)
367 }
368}
369
370impl From<DatabaseErrorKind> for WaeError {
371 fn from(kind: DatabaseErrorKind) -> Self {
372 Self::database(kind)
373 }
374}
375
376pub type WaeResult<T> = Result<T, WaeError>;
378
379#[derive(Debug, Clone, Serialize, Deserialize)]
381pub struct CloudError {
382 pub code: String,
384 pub message: String,
386 pub status: Option<u16>,
388 pub details: Option<serde_json::Value>,
390}
391
392impl CloudError {
393 pub fn new(code: impl Into<String>, message: impl Into<String>) -> Self {
395 Self { code: code.into(), message: message.into(), status: None, details: None }
396 }
397
398 pub fn internal(message: impl Into<String>) -> Self {
400 Self::new("INTERNAL_ERROR", message)
401 }
402
403 pub fn invalid_param(param: impl Into<String>, reason: impl Into<String>) -> Self {
405 Self::new("INVALID_PARAMETER", format!("Invalid parameter '{}': {}", param.into(), reason.into()))
406 }
407
408 pub fn not_found(resource: impl Into<String>) -> Self {
410 Self::new("NOT_FOUND", format!("{} not found", resource.into()))
411 }
412
413 pub fn permission_denied(action: impl Into<String>) -> Self {
415 Self::new("PERMISSION_DENIED", format!("Permission denied for action: {}", action.into()))
416 }
417
418 pub fn timeout(operation: impl Into<String>) -> Self {
420 Self::new("TIMEOUT", format!("Operation timed out: {}", operation.into()))
421 }
422
423 pub fn service_unavailable(service: impl Into<String>) -> Self {
425 Self::new("SERVICE_UNAVAILABLE", format!("Service unavailable: {}", service.into()))
426 }
427
428 pub fn with_status(mut self, status: u16) -> Self {
430 self.status = Some(status);
431 self
432 }
433
434 pub fn with_details(mut self, details: serde_json::Value) -> Self {
436 self.details = Some(details);
437 self
438 }
439}
440
441impl fmt::Display for CloudError {
442 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
443 match self.status {
444 Some(status) => write!(f, "[{}] {} (HTTP {})", self.code, self.message, status),
445 None => write!(f, "[{}] {}", self.code, self.message),
446 }
447 }
448}
449
450impl std::error::Error for CloudError {}
451
452impl From<WaeError> for CloudError {
453 fn from(err: WaeError) -> Self {
454 CloudError::new(format!("{:?}", err.kind), err.message.unwrap_or_default())
455 }
456}
457
458pub type CloudResult<T> = Result<T, CloudError>;