1use std::sync::PoisonError;
4use thiserror::Error;
5
6pub type Result<T> = std::result::Result<T, ThreadError>;
8
9#[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 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 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 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 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 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 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
171impl<T> From<PoisonError<T>> for ThreadError {
173 fn from(err: PoisonError<T>) -> Self {
174 ThreadError::LockPoisoned(err.to_string())
175 }
176}
177
178impl<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}