Skip to main content

tightbeam/
error.rs

1#[cfg(not(feature = "std"))]
2extern crate alloc;
3#[cfg(not(feature = "std"))]
4use alloc::vec::Vec;
5
6use crate::spki::ObjectIdentifier;
7use crate::Version;
8
9#[cfg(feature = "derive")]
10use crate::Errorizable;
11
12/// A specialized Result type for TightBeam operations
13pub type Result<T> = core::result::Result<T, TightBeamError>;
14
15/// A specialized Result type for compression operations
16#[cfg(feature = "compress")]
17pub type CompressionResult<T> = core::result::Result<T, CompressionError>;
18
19/// Error indicating a mismatch between received and expected values
20#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
21pub struct ReceivedExpectedError<Received, Expected> {
22	pub received: Received,
23	pub expected: Expected,
24}
25
26impl<Received, Expected> From<(Received, Expected)> for ReceivedExpectedError<Received, Expected> {
27	fn from((received, expected): (Received, Expected)) -> Self {
28		Self { received, expected }
29	}
30}
31
32impl<Received: core::fmt::Debug, Expected: core::fmt::Debug> core::fmt::Display
33	for ReceivedExpectedError<Received, Expected>
34{
35	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
36		write!(f, "expected {:?}, got {:?}", self.expected, self.received)
37	}
38}
39
40#[cfg(feature = "compress")]
41#[cfg_attr(feature = "derive", derive(Errorizable))]
42#[derive(Debug)]
43pub enum CompressionError {
44	#[cfg(feature = "zstd")]
45	#[cfg_attr(feature = "derive", error("ZSTD compression/decompression error: {0}"))]
46	#[cfg_attr(feature = "derive", from)]
47	ZSTD(zeekstd::Error),
48
49	#[cfg_attr(feature = "derive", error("I/O error during compression/decompression: {0}"))]
50	#[cfg_attr(feature = "derive", from)]
51	IO(std::io::Error),
52}
53
54#[cfg(all(feature = "compress", not(feature = "derive")))]
55impl core::fmt::Display for CompressionError {
56	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
57		match self {
58			#[cfg(feature = "zstd")]
59			CompressionError::ZSTD(e) => write!(f, "ZSTD compression/decompression error: {e}"),
60			CompressionError::IO(e) => write!(f, "I/O error during compression/decompression: {e}"),
61		}
62	}
63}
64
65/// Trait for injected faults in testing
66#[cfg(feature = "testing-fault")]
67pub trait InjectedError: core::fmt::Debug + core::fmt::Display + Send + Sync {}
68
69// Blanket implementation for any type meeting the requirements
70#[cfg(feature = "testing-fault")]
71impl<T> InjectedError for T where T: core::fmt::Debug + core::fmt::Display + Send + Sync {}
72
73#[cfg_attr(feature = "derive", derive(Errorizable))]
74#[derive(Debug)]
75pub enum TightBeamError {
76	/// Error from the matrix implementation
77	#[cfg_attr(feature = "derive", error("Matrix error: {0}"))]
78	#[cfg_attr(feature = "derive", from)]
79	MatrixError(crate::matrix::MatrixError),
80
81	#[cfg(feature = "router")]
82	#[cfg_attr(feature = "derive", error("Route error: {0}"))]
83	#[cfg_attr(feature = "derive", from)]
84	RouterError(crate::router::RouterError),
85
86	/// Error from the message builder
87	#[cfg(feature = "builder")]
88	#[cfg_attr(feature = "derive", error("Build error: {0}"))]
89	#[cfg_attr(feature = "derive", from)]
90	BuildError(crate::builder::error::BuildError),
91
92	/// StandardError
93	#[cfg(feature = "standards")]
94	#[cfg_attr(feature = "derive", error("Standard error: {0}"))]
95	#[cfg_attr(feature = "derive", from)]
96	StandardError(crate::standards::error::StandardError),
97
98	#[cfg(feature = "colony")]
99	#[cfg_attr(feature = "derive", error("Drone error: {0}"))]
100	#[cfg_attr(feature = "derive", from)]
101	HiveError(crate::colony::hive::HiveError),
102
103	#[cfg(feature = "colony")]
104	#[cfg_attr(feature = "derive", error("Worker relay error: {0}"))]
105	#[cfg_attr(feature = "derive", from)]
106	WorkerRelay(crate::colony::worker::WorkerRelayError),
107
108	#[cfg(feature = "std")]
109	/// I/O error
110	#[cfg_attr(feature = "derive", error("I/O error: {0}"))]
111	#[cfg_attr(feature = "derive", from)]
112	IoError(std::io::Error),
113
114	#[cfg(feature = "std")]
115	/// Lock poisoned
116	#[cfg_attr(feature = "derive", error("Lock poisoned"))]
117	LockPoisoned,
118
119	/// Invalid or unsupported algorithm identifier
120	#[cfg_attr(feature = "derive", error("Invalid or unsupported object identifier: {0}"))]
121	InvalidOID(crate::der::oid::Error),
122
123	/// Error during signature verification or generation
124	#[cfg(feature = "signature")]
125	#[cfg_attr(feature = "derive", error("Signature verification or generation error: {0}"))]
126	#[cfg_attr(feature = "derive", from)]
127	SignatureError(crate::crypto::sign::Error),
128
129	/// Error from elliptic curve operations
130	#[cfg(feature = "signature")]
131	#[cfg_attr(feature = "derive", error("Elliptic curve error: {0}"))]
132	#[cfg_attr(feature = "derive", from)]
133	EllipticCurveError(crate::crypto::sign::elliptic_curve::Error),
134
135	/// Error during serialization
136	#[cfg_attr(feature = "derive", error("Serialization error: {0}"))]
137	#[cfg_attr(feature = "derive", from)]
138	SerializationError(crate::der::Error),
139
140	/// Error during compression or decompression
141	#[cfg(feature = "compress")]
142	#[cfg_attr(feature = "derive", error("Compression error: {0}"))]
143	#[cfg_attr(feature = "derive", from)]
144	CompressionError(CompressionError),
145
146	/// Error during handshake operations
147	#[cfg(feature = "transport")]
148	#[cfg_attr(feature = "derive", error("Handshake error: {0}"))]
149	#[cfg_attr(feature = "derive", from)]
150	HandshakeError(crate::transport::handshake::HandshakeError),
151
152	#[cfg(feature = "transport")]
153	#[cfg_attr(feature = "derive", error("Transport error: {0}"))]
154	#[cfg_attr(feature = "derive", from)]
155	TransportError(crate::transport::error::TransportError),
156
157	/// Unsupported protocol version
158	#[cfg_attr(
159		feature = "derive",
160		error("Unsupported protocol version: expected {expected:?}, got {received:?}")
161	)]
162	UnsupportedVersion(ReceivedExpectedError<Version, Version>),
163
164	/// Error during testing operations
165	#[cfg(feature = "testing")]
166	#[cfg_attr(feature = "derive", error("Testing error: {0}"))]
167	#[cfg_attr(feature = "derive", from)]
168	TestingError(crate::testing::error::TestingError),
169
170	/// Error during URN validation
171	#[cfg_attr(feature = "derive", error("URN validation error: {0}"))]
172	#[cfg_attr(feature = "derive", from)]
173	UrnValidationError(crate::utils::urn::UrnValidationError),
174
175	/// Error during encryption or decryption
176	#[cfg(feature = "aead")]
177	#[cfg_attr(feature = "derive", error("Encryption or decryption error: {0}"))]
178	#[cfg_attr(feature = "derive", from)]
179	EncryptionError(crate::crypto::aead::Error),
180
181	/// Invalid key length for cryptographic operations
182	#[cfg(feature = "aead")]
183	#[cfg_attr(feature = "derive", error("Invalid key length: {0}"))]
184	#[cfg_attr(feature = "derive", from)]
185	InvalidKeyLength(crypto_common::InvalidLength),
186
187	/// Error during ECIES operations
188	#[cfg(feature = "ecies")]
189	#[cfg_attr(feature = "derive", error("ECIES error: {0}"))]
190	#[cfg_attr(feature = "derive", from)]
191	EciesError(crate::crypto::ecies::EciesError),
192
193	#[cfg(feature = "crypto")]
194	#[cfg_attr(feature = "derive", error("Crypto policy error: {0}"))]
195	#[cfg_attr(feature = "derive", from)]
196	CryptoPolicyError(crate::crypto::policy::CryptoPolicyError),
197
198	/// Error during certificate validation
199	#[cfg(feature = "x509")]
200	#[cfg_attr(feature = "derive", error("Certificate validation error: {0}"))]
201	#[cfg_attr(feature = "derive", from)]
202	CertificateValidationError(crate::crypto::x509::error::CertificateValidationError),
203
204	#[cfg(feature = "kdf")]
205	#[cfg_attr(feature = "derive", error("Key derivation error: {0}"))]
206	#[cfg_attr(feature = "derive", from)]
207	KeyDerivationError(crate::crypto::kdf::KdfError),
208
209	/// Error from key provider operations
210	#[cfg(feature = "crypto")]
211	#[cfg_attr(feature = "derive", error("Key provider error: {0}"))]
212	#[cfg_attr(feature = "derive", from)]
213	KeyError(crate::crypto::key::KeyError),
214
215	/// Error obtaining random bytes from the OS
216	#[cfg(feature = "random")]
217	#[cfg_attr(feature = "derive", error("OS random number generator error: {0}"))]
218	#[cfg_attr(feature = "derive", from)]
219	OsRngError(rand_core::Error),
220
221	/// Error during SPKI operations
222	#[cfg(feature = "x509")]
223	#[cfg_attr(feature = "derive", error("SPKI error: {0}"))]
224	#[cfg_attr(feature = "derive", from)]
225	SpkiError(crate::spki::Error),
226
227	/// Error during X.509 certificate building
228	#[cfg(feature = "x509")]
229	#[cfg_attr(feature = "derive", error("X.509 builder error: {0}"))]
230	#[cfg_attr(feature = "derive", from)]
231	X509BuilderError(x509_cert::builder::Error),
232
233	/// Error receiving from channel with timeout
234	#[cfg(feature = "std")]
235	#[cfg_attr(feature = "derive", error("Channel receive timeout error"))]
236	RecvTimeoutError,
237
238	/// Error decoding signature from bytes
239	#[cfg(feature = "signature")]
240	#[cfg_attr(feature = "derive", error("Signature encoding error"))]
241	SignatureEncodingError,
242
243	/// Invalid metadata
244	#[cfg_attr(feature = "derive", error("Invalid metadata"))]
245	InvalidMetadata,
246
247	/// Invalid message body
248	#[cfg_attr(feature = "derive", error("Invalid message body"))]
249	InvalidBody,
250
251	/// Invalid overflow value
252	#[cfg_attr(feature = "derive", error("Invalid overflow value"))]
253	InvalidOverflowValue,
254
255	/// Invalid order
256	#[cfg_attr(feature = "derive", error("Invalid order"))]
257	InvalidOrder,
258
259	// Missing order
260	#[cfg_attr(feature = "derive", error("Missing order"))]
261	MissingOrder,
262
263	/// Missing inflator
264	#[cfg_attr(feature = "derive", error("Missing inflator"))]
265	MissingInflator,
266
267	/// Missing feature
268	#[cfg_attr(feature = "derive", error("Missing feature: {0}"))]
269	MissingFeature(&'static str),
270
271	/// Missing priority
272	#[cfg_attr(feature = "derive", error("Missing priority"))]
273	MissingPriority,
274
275	/// Missing response
276	#[cfg_attr(feature = "derive", error("Missing response"))]
277	MissingResponse,
278
279	/// Signature is missing
280	#[cfg(feature = "signature")]
281	#[cfg_attr(feature = "derive", error("Missing signature"))]
282	MissingSignature,
283
284	/// Signature info is missing
285	#[cfg(feature = "signature")]
286	#[cfg_attr(feature = "derive", error("Missing signature info"))]
287	MissingSignatureInfo,
288
289	/// Missing Encryption Info
290	#[cfg(feature = "aead")]
291	#[cfg_attr(feature = "derive", error("Missing encryption info"))]
292	MissingEncryptionInfo,
293
294	/// Missing Integrity Info
295	#[cfg(feature = "digest")]
296	#[cfg_attr(feature = "derive", error("Missing integrity info"))]
297	MissingDigestInfo,
298
299	/// Missing Compression Info
300	#[cfg_attr(feature = "derive", error("Missing compression info"))]
301	MissingCompressedData,
302
303	/// Invalid algorithm for the message profile
304	#[cfg_attr(feature = "derive", error("Invalid algorithm for message profile"))]
305	InvalidAlgorithm,
306
307	/// Unexpected algorithm for the message profile
308	#[cfg_attr(
309		feature = "derive",
310		error("Unexpected algorithm for message profile: expected {expected:?}, got {received:?}")
311	)]
312	UnexpectedAlgorithm(ReceivedExpectedError<ObjectIdentifier, ObjectIdentifier>),
313
314	/// Missing or invalid configuration
315	#[cfg_attr(feature = "derive", error("Missing configuration"))]
316	MissingConfiguration,
317
318	/// Operation not supported by this implementation
319	#[cfg_attr(feature = "derive", error("Unsupported operation"))]
320	UnsupportedOperation,
321
322	/// Hive already established
323	#[cfg(feature = "colony")]
324	#[cfg_attr(feature = "derive", error("Hive already established"))]
325	AlreadyEstablished,
326
327	/// Task join error
328	#[cfg(feature = "colony")]
329	#[cfg_attr(feature = "derive", error("Task join failed"))]
330	JoinError,
331
332	/// Multiple errors collected together
333	#[cfg_attr(feature = "derive", error("Multiple errors occurred: {0:?}"))]
334	Sequence(Vec<TightBeamError>),
335
336	/// Injected fault for testing (any error type)
337	#[cfg(feature = "testing-fault")]
338	#[cfg_attr(feature = "derive", error("Injected fault: {0}"))]
339	InjectedFault(Box<dyn InjectedError>),
340}
341
342#[cfg(all(feature = "colony", not(feature = "derive")))]
343impl From<crate::colony::WorkerRelayError> for TightBeamError {
344	fn from(err: crate::colony::WorkerRelayError) -> Self {
345		TightBeamError::WorkerRelay(err)
346	}
347}
348
349#[cfg(not(feature = "derive"))]
350impl core::fmt::Display for TightBeamError {
351	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
352		match self {
353			TightBeamError::SerializationError(err) => write!(f, "Serialization error: {err}"),
354			#[cfg(feature = "router")]
355			TightBeamError::RouterError(err) => write!(f, "Route error: {err}"),
356			TightBeamError::InvalidMetadata => write!(f, "Invalid metadata"),
357			TightBeamError::InvalidBody => write!(f, "Invalid message body"),
358			TightBeamError::InvalidOID(err) => {
359				write!(f, "Invalid or unsupported object identifier: {err}")
360			}
361			TightBeamError::InvalidOverflowValue => write!(f, "Invalid overflow value"),
362			TightBeamError::InvalidOrder => write!(f, "Invalid order"),
363			TightBeamError::MissingInflator => write!(f, "Missing inflator"),
364			TightBeamError::MissingOrder => write!(f, "Missing order"),
365			TightBeamError::MissingPriority => write!(f, "Missing priority"),
366			TightBeamError::MissingResponse => write!(f, "Missing response"),
367			TightBeamError::MissingFeature(feature) => write!(f, "Missing feature: {feature}"),
368			TightBeamError::MissingConfiguration => write!(f, "Missing configuration"),
369			TightBeamError::UnsupportedOperation => write!(f, "Unsupported operation"),
370			#[cfg(feature = "transport")]
371			TightBeamError::HandshakeError(err) => write!(f, "Handshake error: {err}"),
372			#[cfg(feature = "colony")]
373			TightBeamError::HiveError(err) => write!(f, "Drone error: {err}"),
374			#[cfg(feature = "std")]
375			TightBeamError::LockPoisoned => write!(f, "Lock poisoned"),
376			#[cfg(feature = "standards")]
377			TightBeamError::StandardError(err) => write!(f, "Standard error: {err}"),
378			#[cfg(feature = "random")]
379			TightBeamError::OsRngError(err) => write!(f, "OS random number generator error: {err}"),
380			#[cfg(feature = "x509")]
381			TightBeamError::SpkiError(err) => write!(f, "SPKI error: {err}"),
382			#[cfg(feature = "x509")]
383			TightBeamError::X509BuilderError(err) => write!(f, "X.509 builder error: {err}"),
384			#[cfg(feature = "std")]
385			TightBeamError::RecvTimeoutError => write!(f, "Channel receive timeout error"),
386			#[cfg(feature = "aead")]
387			TightBeamError::EncryptionError(err) => {
388				write!(f, "Encryption or decryption error: {err}")
389			}
390			#[cfg(feature = "aead")]
391			TightBeamError::InvalidKeyLength(_) => {
392				write!(f, "Invalid key length")
393			}
394			#[cfg(feature = "ecies")]
395			TightBeamError::EciesError(err) => write!(f, "ECIES error: {err}"),
396			#[cfg(feature = "signature")]
397			TightBeamError::SignatureError(err) => {
398				write!(f, "Signature verification or generation error: {err}")
399			}
400			#[cfg(feature = "signature")]
401			TightBeamError::EllipticCurveError(_) => write!(f, "Elliptic curve error"),
402			#[cfg(feature = "signature")]
403			TightBeamError::SignatureEncodingError => write!(f, "Signature encoding error"),
404			TightBeamError::KeyError(err) => write!(f, "Key provider error: {err}"),
405			#[cfg(feature = "digest")]
406			TightBeamError::MissingDigestInfo => write!(f, "Missing integrity info"),
407			#[cfg(feature = "aead")]
408			TightBeamError::MissingEncryptionInfo => write!(f, "Missing encryption info"),
409			#[cfg(feature = "signature")]
410			TightBeamError::MissingSignatureInfo => write!(f, "Missing signature info"),
411			#[cfg(feature = "signature")]
412			TightBeamError::MissingSignature => write!(f, "Missing signature"),
413			TightBeamError::MissingCompressedData => write!(f, "Missing compression info"),
414			TightBeamError::InvalidAlgorithm => write!(f, "Invalid algorithm for message profile"),
415			TightBeamError::UnexpectedAlgorithm(err) => {
416				write!(
417					f,
418					"Unexpected algorithm for message profile: expected {:?}, got {:?}",
419					err.expected, err.received
420				)
421			}
422			#[cfg(feature = "compress")]
423			TightBeamError::CompressionError(err) => match err {
424				#[cfg(feature = "zstd")]
425				CompressionError::ZSTD(e) => write!(f, "ZSTD compression/decompression error: {e}"),
426				CompressionError::IO(e) => {
427					write!(f, "I/O error during compression/decompression: {e}")
428				}
429			},
430			TightBeamError::Sequence(errors) => {
431				write!(f, "Multiple errors: ")?;
432				for (i, error) in errors.iter().enumerate() {
433					if i > 0 {
434						write!(f, "; ")?;
435					}
436					write!(f, "{error}")?;
437				}
438				Ok(())
439			}
440			#[cfg(feature = "colony")]
441			TightBeamError::AlreadyEstablished => write!(f, "Hive already established"),
442			#[cfg(feature = "colony")]
443			TightBeamError::JoinError => write!(f, "Task join failed"),
444			TightBeamError::UnsupportedVersion(err) => {
445				write!(
446					f,
447					"Unsupported protocol version: expected {:?}, got {:?}",
448					err.expected, err.received
449				)
450			}
451			#[cfg(feature = "testing")]
452			TightBeamError::TestingError(err) => write!(f, "Testing error: {err}"),
453			TightBeamError::UrnValidationError(err) => write!(f, "URN validation error: {err}"),
454			#[cfg(feature = "testing-fault")]
455			TightBeamError::InjectedFault(err) => write!(f, "Injected fault: {err}"),
456		}
457	}
458}
459
460#[cfg(feature = "std")]
461crate::impl_from!(std::string::FromUtf8Error => TightBeamError::IoError via |err| std::io::Error::new(std::io::ErrorKind::InvalidData, err));
462#[cfg(feature = "std")]
463crate::impl_from!(std::net::AddrParseError => TightBeamError::IoError via |err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err));
464
465// ============================================================================
466// Non-derive From implementations
467// When `derive` feature is disabled, these provide the From impls that would
468// otherwise be generated by the Errorizable derive macro's #[from] attribute.
469// ============================================================================
470
471#[cfg(not(feature = "derive"))]
472crate::impl_from!(der::Error => TightBeamError::SerializationError);
473#[cfg(not(feature = "derive"))]
474crate::impl_from!(crate::matrix::MatrixError => TightBeamError::MatrixError);
475#[cfg(not(feature = "derive"))]
476crate::impl_from!(crate::utils::urn::UrnValidationError => TightBeamError::UrnValidationError);
477#[cfg(all(feature = "crypto", not(feature = "derive")))]
478crate::impl_from!(crate::crypto::policy::CryptoPolicyError => TightBeamError::CryptoPolicyError);
479#[cfg(all(feature = "kdf", not(feature = "derive")))]
480crate::impl_from!(crate::crypto::kdf::KdfError => TightBeamError::KeyDerivationError);
481#[cfg(all(feature = "crypto", not(feature = "derive")))]
482crate::impl_from!(crate::crypto::key::KeyError => TightBeamError::KeyError);
483
484#[cfg(all(feature = "std", not(feature = "derive")))]
485crate::impl_from!(std::io::Error => TightBeamError::IoError);
486
487#[cfg(all(feature = "router", not(feature = "derive")))]
488crate::impl_from!(crate::router::RouterError => TightBeamError::RouterError);
489
490#[cfg(all(feature = "builder", not(feature = "derive")))]
491crate::impl_from!(crate::builder::error::BuildError => TightBeamError::BuildError);
492
493#[cfg(all(feature = "standards", not(feature = "derive")))]
494crate::impl_from!(crate::standards::error::StandardError => TightBeamError::StandardError);
495
496#[cfg(all(feature = "colony", not(feature = "derive")))]
497crate::impl_from!(crate::colony::hive::HiveError => TightBeamError::HiveError);
498#[cfg(all(feature = "colony", not(feature = "derive")))]
499crate::impl_from!(crate::colony::worker::WorkerRelayError => TightBeamError::WorkerRelay);
500
501#[cfg(all(feature = "transport", not(feature = "derive")))]
502crate::impl_from!(crate::transport::handshake::HandshakeError => TightBeamError::HandshakeError);
503#[cfg(all(feature = "transport", not(feature = "derive")))]
504crate::impl_from!(crate::transport::error::TransportError => TightBeamError::TransportError);
505
506#[cfg(all(feature = "random", not(feature = "derive")))]
507crate::impl_from!(getrandom::Error => TightBeamError::OsRngError);
508
509#[cfg(all(feature = "x509", not(feature = "derive")))]
510crate::impl_from!(spki::Error => TightBeamError::SpkiError);
511#[cfg(all(feature = "x509", not(feature = "derive")))]
512crate::impl_from!(x509_cert::builder::Error => TightBeamError::X509BuilderError);
513
514#[cfg(all(feature = "compress", not(feature = "derive")))]
515crate::impl_from!(CompressionError => TightBeamError::CompressionError);
516#[cfg(all(feature = "std", feature = "compress", not(feature = "derive")))]
517crate::impl_from!(std::io::Error => CompressionError::IO);
518
519#[cfg(all(feature = "aead", not(feature = "derive")))]
520crate::impl_from!(aead::Error => TightBeamError::EncryptionError);
521#[cfg(all(feature = "aead", not(feature = "derive")))]
522crate::impl_from!(crypto_common::InvalidLength => TightBeamError::InvalidKeyLength);
523
524#[cfg(all(feature = "ecies", not(feature = "derive")))]
525crate::impl_from!(EciesError => TightBeamError::EciesError);
526
527#[cfg(all(feature = "signature", not(feature = "derive")))]
528crate::impl_from!(signature::Error => TightBeamError::SignatureError);
529#[cfg(all(feature = "signature", not(feature = "derive")))]
530crate::impl_from!(crate::crypto::sign::elliptic_curve::Error => TightBeamError::EllipticCurveError);
531
532#[cfg(all(feature = "zstd", not(feature = "derive")))]
533crate::impl_from!(zeekstd::Error => TightBeamError::CompressionError via CompressionError::ZSTD);
534#[cfg(all(feature = "zstd", not(feature = "derive")))]
535crate::impl_from!(zeekstd::Error => CompressionError::ZSTD);
536#[cfg(all(feature = "testing", not(feature = "derive")))]
537crate::impl_from!(crate::testing::error::TestingError => TightBeamError::TestingError);
538#[cfg(all(feature = "std", not(feature = "derive")))]
539crate::impl_from!(std::sync::mpsc::RecvTimeoutError => TightBeamError::RecvTimeoutError discard);
540
541#[cfg(not(feature = "derive"))]
542impl core::error::Error for TightBeamError {}
543#[cfg(all(feature = "compress", not(feature = "derive")))]
544impl core::error::Error for CompressionError {}
545
546// Generic type to unit variant - requires manual impl due to generic T
547#[cfg(feature = "std")]
548impl<T> From<std::sync::PoisonError<T>> for TightBeamError {
549	fn from(_: std::sync::PoisonError<T>) -> Self {
550		TightBeamError::LockPoisoned
551	}
552}