1use core::fmt;
2
3pub const ERR_UNKNOWN_HOST: u16 = 0x0001;
5pub const ERR_INVALID_COMMAND: u16 = 0x0002;
7pub const ERR_INVALID_REGISTER: u16 = 0x0003;
9pub const ERR_INVALID_OFFSET: u16 = 0x0004;
11pub const ERR_INVALID_REPLY: u16 = 0x0005;
13pub const ERR_OVERFLOW: u16 = 0x0006;
15pub const ERR_INVALID_VERSION: u16 = 0x0007;
17pub const ERR_IO: u16 = 0x0008;
19pub const ERR_INVALID_DATA: u16 = 0x0009;
21pub const ERR_PACKER: u16 = 0x0010;
23pub const ERR_FAILED: u16 = 0x0000;
25
26#[derive(thiserror::Error, Debug)]
28pub enum Error {
29 #[error("Host unknown")]
31 UnknownHost,
32 #[error("Invalid command")]
34 InvalidCommand,
35 #[error("Invalid register")]
37 InvalidRegister,
38 #[error("Invalid offset")]
40 InvalidOffset,
41 #[error("Invalid reply")]
43 InvalidReply,
44
45 #[error("Overflow")]
47 Overflow,
48 #[error("Invalid version")]
50 UnsupportedVersion,
51 #[error("I/O: {0}")]
53 Io(#[from] std::io::Error),
54 #[error("Invalid data")]
56 InvalidData,
57 #[error("Packer: {0}")]
59 Packer(#[from] binrw::Error),
60 #[error("Failed: {0}")]
62 Failed(String),
63}
64
65impl From<Error> for Vec<u8> {
66 fn from(err: Error) -> Self {
67 let mut buf = Vec::<u8>::with_capacity(2);
68 buf.extend_from_slice(&err.code().to_le_bytes());
69 match err {
70 Error::Io(e) => buf.extend_from_slice(e.to_string().as_bytes()),
71 Error::Packer(e) => buf.extend_from_slice(e.to_string().as_bytes()),
72 Error::Failed(msg) => buf.extend_from_slice(msg.as_bytes()),
73 _ => (),
74 }
75 buf
76 }
77}
78
79impl From<std::num::TryFromIntError> for Error {
80 fn from(_: std::num::TryFromIntError) -> Self {
81 Self::Overflow
82 }
83}
84
85impl From<&[u8]> for Error {
86 fn from(slice: &[u8]) -> Self {
87 if slice.len() < 2 {
88 return Error::Failed(String::new());
89 }
90 let code = u16::from_le_bytes(slice[..2].try_into().unwrap());
91 let msg = std::str::from_utf8(&slice[2..]).unwrap_or_default();
92 match code {
93 ERR_UNKNOWN_HOST => Self::UnknownHost,
94 ERR_INVALID_COMMAND => Self::InvalidCommand,
95 ERR_INVALID_REGISTER => Self::InvalidRegister,
96 ERR_INVALID_OFFSET => Self::InvalidOffset,
97 ERR_INVALID_REPLY => Self::InvalidReply,
98 ERR_OVERFLOW => Self::Overflow,
99 ERR_INVALID_VERSION => Self::UnsupportedVersion,
100 ERR_IO => Self::Io(std::io::Error::new(std::io::ErrorKind::Other, msg)),
101 ERR_INVALID_DATA => Self::InvalidData,
102 ERR_FAILED => Self::Failed(msg.to_string()),
103 _ => Self::Failed(format!("Unknown error code: 0x{:04X}", code)),
104 }
105 }
106}
107
108impl From<u16> for Error {
109 fn from(e: u16) -> Self {
110 match e {
111 ERR_UNKNOWN_HOST => Self::UnknownHost,
112 ERR_INVALID_COMMAND => Self::InvalidCommand,
113 ERR_INVALID_REGISTER => Self::InvalidRegister,
114 ERR_INVALID_OFFSET => Self::InvalidOffset,
115 ERR_INVALID_REPLY => Self::InvalidReply,
116 ERR_OVERFLOW => Self::Overflow,
117 ERR_INVALID_VERSION => Self::UnsupportedVersion,
118 ERR_IO => Self::Io(std::io::Error::new(std::io::ErrorKind::Other, "I/O error")),
119 ERR_INVALID_DATA => Self::InvalidData,
120 _ => Self::Failed(format!("Unknown error code: 0x{:04X}", e)),
121 }
122 }
123}
124
125impl Error {
126 pub const fn code(&self) -> u16 {
128 match self {
129 Self::UnknownHost => ERR_UNKNOWN_HOST,
130 Self::InvalidCommand => ERR_INVALID_COMMAND,
131 Self::InvalidRegister => ERR_INVALID_REGISTER,
132 Self::InvalidOffset => ERR_INVALID_OFFSET,
133 Self::InvalidReply => ERR_INVALID_REPLY,
134 Self::Overflow => ERR_OVERFLOW,
135 Self::UnsupportedVersion => ERR_INVALID_VERSION,
136 Self::Io(_) => ERR_IO,
137 Self::InvalidData => ERR_INVALID_DATA,
138 Self::Packer(_) => ERR_PACKER,
139 Self::Failed(_) => ERR_FAILED,
140 }
141 }
142 pub fn failed<D: fmt::Display>(msg: D) -> Self {
144 Self::Failed(msg.to_string())
145 }
146}