1use piper_can::CanError;
4use piper_protocol::ProtocolError;
5use thiserror::Error;
6
7#[derive(Error, Debug)]
9pub enum DriverError {
10 #[error("CAN driver error: {0}")]
12 Can(#[from] CanError),
13
14 #[error("Protocol error: {0}")]
16 Protocol(#[from] ProtocolError),
17
18 #[error("Command channel closed")]
20 ChannelClosed,
21
22 #[error("Command channel full (buffer size: 10)")]
24 ChannelFull,
25
26 #[error("Not in dual-thread mode. Use `new_dual_thread()` instead of `new()`")]
30 NotDualThread,
31
32 #[error("Poisoned lock (thread panic)")]
34 PoisonedLock,
35
36 #[error("IO thread error: {0}")]
38 IoThread(String),
39
40 #[error("Not implemented: {0}")]
42 NotImplemented(String),
43
44 #[error("Operation timeout")]
46 Timeout,
47
48 #[error("Invalid input: {0}")]
50 InvalidInput(String),
51}
52
53#[cfg(test)]
54mod tests {
55 use super::DriverError;
56 use piper_can::CanError;
57 use piper_protocol::ProtocolError;
58
59 #[test]
61 fn test_driver_error_display() {
62 let can_error = CanError::Timeout;
64 let driver_error = DriverError::Can(can_error);
65 let msg = format!("{}", driver_error);
66 assert!(
67 msg.contains("Read timeout") || msg.contains("CAN"),
68 "Can error message: {}",
69 msg
70 );
71
72 let protocol_error = ProtocolError::InvalidLength {
74 expected: 8,
75 actual: 4,
76 };
77 let driver_error = DriverError::Protocol(protocol_error);
78 let msg = format!("{}", driver_error);
79 assert!(
80 msg.contains("Invalid frame length"),
81 "Protocol error message: {}",
82 msg
83 );
84
85 let driver_error = DriverError::ChannelClosed;
87 let msg = format!("{}", driver_error);
88 assert_eq!(msg, "Command channel closed");
89
90 let driver_error = DriverError::ChannelFull;
92 let msg = format!("{}", driver_error);
93 assert!(msg.contains("channel full") || msg.contains("ChannelFull"));
94
95 let driver_error = DriverError::PoisonedLock;
97 let msg = format!("{}", driver_error);
98 assert!(msg.contains("Poisoned lock") || msg.contains("PoisonedLock"));
99
100 let driver_error = DriverError::IoThread("test error".to_string());
102 let msg = format!("{}", driver_error);
103 assert!(msg.contains("IO thread") && msg.contains("test error"));
104
105 let driver_error = DriverError::NotImplemented("feature".to_string());
107 let msg = format!("{}", driver_error);
108 assert!(msg.contains("Not implemented") && msg.contains("feature"));
109
110 let driver_error = DriverError::Timeout;
112 let msg = format!("{}", driver_error);
113 assert_eq!(msg, "Operation timeout");
114 }
115
116 #[test]
118 fn test_from_can_error() {
119 let can_error = CanError::Timeout;
120 let driver_error: DriverError = can_error.into();
121 match driver_error {
122 DriverError::Can(e) => assert!(matches!(e, CanError::Timeout)),
123 _ => panic!("Expected Can variant"),
124 }
125 }
126
127 #[test]
129 fn test_from_protocol_error() {
130 let protocol_error = ProtocolError::InvalidCanId { id: 0x123 };
131 let driver_error: DriverError = protocol_error.into();
132 match driver_error {
133 DriverError::Protocol(e) => match e {
134 ProtocolError::InvalidCanId { id } => assert_eq!(id, 0x123),
135 _ => panic!("Expected InvalidCanId variant"),
136 },
137 _ => panic!("Expected Protocol variant"),
138 }
139 }
140}