1use thiserror::Error;
4
5use crate::validation::ValidationError;
6
7#[derive(Debug, Error)]
14#[non_exhaustive]
15pub enum RvcsiError {
16 #[error("adapter '{kind}' failed: {message}")]
18 Adapter {
19 kind: String,
21 message: String,
23 },
24
25 #[error("parse error at offset {offset}: {message}")]
27 Parse {
28 offset: usize,
30 message: String,
32 },
33
34 #[error("frame rejected: {0}")]
36 Validation(#[from] ValidationError),
37
38 #[error("invalid configuration: {0}")]
40 Config(String),
41
42 #[error("io error: {0}")]
44 Io(#[from] std::io::Error),
45
46 #[error("serde error: {0}")]
48 Serde(#[from] serde_json::Error),
49
50 #[error("unsupported: {0}")]
52 Unsupported(String),
53}
54
55impl RvcsiError {
56 pub fn adapter(kind: impl Into<String>, message: impl Into<String>) -> Self {
58 RvcsiError::Adapter {
59 kind: kind.into(),
60 message: message.into(),
61 }
62 }
63
64 pub fn parse(offset: usize, message: impl Into<String>) -> Self {
66 RvcsiError::Parse {
67 offset,
68 message: message.into(),
69 }
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn display_messages_are_useful() {
79 let e = RvcsiError::adapter("nexmon", "device /dev/wlan0 not in monitor mode");
80 assert!(e.to_string().contains("nexmon"));
81 assert!(e.to_string().contains("monitor mode"));
82
83 let e = RvcsiError::parse(12, "frame length 0");
84 assert!(e.to_string().contains("offset 12"));
85 }
86}