pokeys_thread/
error.rs

1//! Error types for the pokeys-thread crate
2
3use std::sync::PoisonError;
4use thiserror::Error;
5
6/// Result type used throughout the crate
7pub type Result<T> = std::result::Result<T, ThreadError>;
8
9/// Main error type for threading operations
10#[derive(Error, Debug)]
11pub enum ThreadError {
12    #[error("Thread not found: {0}")]
13    ThreadNotFound(u32),
14
15    #[error("Thread already exists: {0}")]
16    ThreadAlreadyExists(u32),
17
18    #[error("Thread creation failed: {0}")]
19    ThreadCreationFailed(String),
20
21    #[error("Command send failed: {0}")]
22    CommandSendFailed(String),
23
24    #[error("Device error: {0}")]
25    DeviceError(#[from] pokeys_lib::PoKeysError),
26
27    #[error("IO error: {0}")]
28    IoError(#[from] std::io::Error),
29
30    #[error("Thread join error")]
31    ThreadJoinError,
32
33    #[error("Invalid command: {0}")]
34    InvalidCommand(String),
35
36    #[error("Operation timeout")]
37    Timeout,
38
39    #[error("Operation not supported")]
40    NotSupported,
41
42    #[error("Invalid parameter: {0}")]
43    InvalidParameter(String),
44
45    #[error("Operation failed: {0}")]
46    OperationFailed(String),
47
48    #[error("Lock poisoned: {0}")]
49    LockPoisoned(String),
50
51    #[error("Channel receive error: {0}")]
52    ChannelReceiveError(String),
53
54    #[error("Channel send error: {0}")]
55    ChannelSendError(String),
56
57    #[error("State error: {0}")]
58    StateError(String),
59
60    #[error("Connection error: {0}")]
61    ConnectionError(String),
62
63    #[error("Initialization error: {0}")]
64    InitializationError(String),
65
66    #[error("Configuration error: {0}")]
67    ConfigurationError(String),
68
69    #[error("Invalid thread ID: {0}")]
70    InvalidThreadId(usize),
71
72    #[error("Unsupported device type")]
73    UnsupportedDevice,
74
75    #[error("Pin capability error: {message}")]
76    PinCapabilityError {
77        message: String,
78        pin: u8,
79        capability: String,
80        suggestion: Option<String>,
81    },
82
83    #[error("Hardware constraint violation: {message}")]
84    HardwareConstraint {
85        message: String,
86        constraint: String,
87        suggestion: String,
88    },
89
90    #[error("Validation failed: {message}")]
91    ValidationError {
92        message: String,
93        context: String,
94        recovery_suggestion: Option<String>,
95    },
96
97    #[error("Resource conflict: {message}")]
98    ResourceConflict {
99        message: String,
100        resource: String,
101        conflicting_operation: String,
102    },
103
104    #[error("Other error: {0}")]
105    Other(String),
106}
107
108impl ThreadError {
109    /// Create a pin capability error with context
110    pub fn pin_capability_error(pin: u8, capability: &str, suggestion: Option<String>) -> Self {
111        Self::PinCapabilityError {
112            message: format!("Pin {} does not support {}", pin, capability),
113            pin,
114            capability: capability.to_string(),
115            suggestion,
116        }
117    }
118
119    /// Create a hardware constraint error
120    pub fn hardware_constraint(constraint: &str, suggestion: &str) -> Self {
121        Self::HardwareConstraint {
122            message: format!("Hardware constraint violated: {}", constraint),
123            constraint: constraint.to_string(),
124            suggestion: suggestion.to_string(),
125        }
126    }
127
128    /// Create a validation error with recovery suggestion
129    pub fn validation_error(message: &str, context: &str, recovery: Option<&str>) -> Self {
130        Self::ValidationError {
131            message: message.to_string(),
132            context: context.to_string(),
133            recovery_suggestion: recovery.map(|s| s.to_string()),
134        }
135    }
136
137    /// Create a resource conflict error
138    pub fn resource_conflict(resource: &str, operation: &str) -> Self {
139        Self::ResourceConflict {
140            message: format!("Resource {} is already in use", resource),
141            resource: resource.to_string(),
142            conflicting_operation: operation.to_string(),
143        }
144    }
145
146    /// Get recovery suggestion if available
147    pub fn recovery_suggestion(&self) -> Option<&str> {
148        match self {
149            Self::PinCapabilityError { suggestion, .. } => suggestion.as_deref(),
150            Self::HardwareConstraint { suggestion, .. } => Some(suggestion),
151            Self::ValidationError {
152                recovery_suggestion,
153                ..
154            } => recovery_suggestion.as_deref(),
155            _ => None,
156        }
157    }
158
159    /// Check if error is recoverable
160    pub fn is_recoverable(&self) -> bool {
161        matches!(
162            self,
163            Self::PinCapabilityError { .. }
164                | Self::ValidationError { .. }
165                | Self::InvalidParameter(_)
166                | Self::ConfigurationError(_)
167        )
168    }
169}
170
171// Implement From for PoisonError
172impl<T> From<PoisonError<T>> for ThreadError {
173    fn from(err: PoisonError<T>) -> Self {
174        ThreadError::LockPoisoned(err.to_string())
175    }
176}
177
178// Implement From for channel errors
179impl<T> From<std::sync::mpsc::SendError<T>> for ThreadError {
180    fn from(err: std::sync::mpsc::SendError<T>) -> Self {
181        ThreadError::ChannelSendError(err.to_string())
182    }
183}
184
185impl From<std::sync::mpsc::RecvError> for ThreadError {
186    fn from(err: std::sync::mpsc::RecvError) -> Self {
187        ThreadError::ChannelReceiveError(err.to_string())
188    }
189}
190
191impl From<std::sync::mpsc::TryRecvError> for ThreadError {
192    fn from(err: std::sync::mpsc::TryRecvError) -> Self {
193        ThreadError::ChannelReceiveError(err.to_string())
194    }
195}