gosh_dl/protocol/
error.rs

1//! Protocol-level errors
2//!
3//! Simplified error types for the engine boundary.
4//! These hide internal implementation details while providing
5//! enough information for consumers to handle errors appropriately.
6
7use serde::{Deserialize, Serialize};
8use std::fmt;
9
10/// Protocol-level error returned from engine operations
11///
12/// This is a simplified error type that hides internal engine details
13/// while providing actionable information to consumers.
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub enum ProtocolError {
16    /// Download was not found
17    NotFound {
18        /// The ID that was not found
19        id: String,
20    },
21
22    /// Invalid state for requested operation
23    InvalidState {
24        /// The action that was attempted
25        action: String,
26        /// The current state that prevented the action
27        current_state: String,
28    },
29
30    /// Invalid input provided
31    InvalidInput {
32        /// The field with invalid input
33        field: String,
34        /// Description of what's wrong
35        message: String,
36    },
37
38    /// Network error occurred
39    Network {
40        /// Error description
41        message: String,
42        /// Whether the operation can be retried
43        retryable: bool,
44    },
45
46    /// Storage/filesystem error
47    Storage {
48        /// Error description
49        message: String,
50    },
51
52    /// Engine is shutting down
53    Shutdown,
54
55    /// Internal engine error (opaque to consumer)
56    Internal {
57        /// Error description
58        message: String,
59    },
60}
61
62impl fmt::Display for ProtocolError {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        match self {
65            Self::NotFound { id } => write!(f, "Download not found: {}", id),
66            Self::InvalidState {
67                action,
68                current_state,
69            } => write!(f, "Cannot {} while {}", action, current_state),
70            Self::InvalidInput { field, message } => {
71                write!(f, "Invalid input for '{}': {}", field, message)
72            }
73            Self::Network { message, .. } => write!(f, "Network error: {}", message),
74            Self::Storage { message } => write!(f, "Storage error: {}", message),
75            Self::Shutdown => write!(f, "Engine is shutting down"),
76            Self::Internal { message } => write!(f, "Internal error: {}", message),
77        }
78    }
79}
80
81impl std::error::Error for ProtocolError {}
82
83impl ProtocolError {
84    /// Check if this error is retryable
85    pub fn is_retryable(&self) -> bool {
86        match self {
87            Self::Network { retryable, .. } => *retryable,
88            _ => false,
89        }
90    }
91}
92
93/// Result type for protocol operations
94pub type ProtocolResult<T> = std::result::Result<T, ProtocolError>;