1#[cfg(feature = "descriptive-errors")]
4use alloc::borrow::Cow;
5
6use no_std_io::io::ErrorKind;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct NeedSize {
11 bits: usize,
12}
13
14impl NeedSize {
15 #[inline]
17 pub fn new(bits: usize) -> Self {
18 Self { bits }
19 }
20
21 #[inline]
23 pub fn bit_size(&self) -> usize {
24 self.bits
25 }
26
27 #[inline]
29 pub fn byte_size(&self) -> usize {
30 self.bits.div_ceil(8)
31 }
32}
33
34#[cfg(feature = "descriptive-errors")]
35type DekuErrorString = Cow<'static, str>;
36
37#[cfg(not(feature = "descriptive-errors"))]
38type DekuErrorString = &'static str;
39
40#[derive(Debug, Clone, PartialEq, Eq)]
42#[non_exhaustive]
43pub enum DekuError {
44 Incomplete(NeedSize),
46 Parse(DekuErrorString),
48 InvalidParam(DekuErrorString),
50 Assertion(DekuErrorString),
52 IdVariantNotFound,
54 Io(ErrorKind),
56}
57
58#[cfg(feature = "descriptive-errors")]
78#[macro_export]
79macro_rules! deku_error {
80 ($p:path, $desc:expr, $fmt:expr, $($arg:expr),*) => {{
81 extern crate alloc;
82 $p(alloc::borrow::Cow::from(alloc::format!(concat!($desc, ": ", $fmt), $($arg),*)))
83 }};
84 ($p:path, $desc:expr, $fmt:expr) => {{
85 extern crate alloc;
86 $p(alloc::borrow::Cow::from(alloc::format!(concat!($desc, ": ", $fmt))))
87 }};
88 ($p:path, $desc:expr) => {{
89 extern crate alloc;
90 $p(alloc::borrow::Cow::from($desc))
91 }};
92 ($p:path) => {{ $p }};
93}
94
95#[cfg(not(feature = "descriptive-errors"))]
114#[macro_export]
115macro_rules! deku_error {
116 ($p:path, $desc:expr, $fmt:expr, $($arg:expr),*) => {{
117 $(let _ = $arg;)*
118 $p($desc)
119 }};
120 ($p:path, $desc:expr, $fmt:expr) => {{
121 $p($desc)
122 }};
123 ($p:path, $desc:expr) => {{
124 $p($desc)
125 }};
126 ($p:path) => {{ $p }};
127}
128
129impl From<core::num::TryFromIntError> for DekuError {
130 fn from(e: core::num::TryFromIntError) -> DekuError {
131 deku_error!(DekuError::Parse, "error parsing int", "{}", e)
132 }
133}
134
135impl From<core::array::TryFromSliceError> for DekuError {
136 fn from(e: core::array::TryFromSliceError) -> DekuError {
137 deku_error!(DekuError::Parse, "error parsing from slice", "{}", e)
138 }
139}
140
141impl From<core::convert::Infallible> for DekuError {
142 fn from(_e: core::convert::Infallible) -> DekuError {
143 unreachable!();
144 }
145}
146
147#[cfg(feature = "std")]
148impl core::fmt::Display for DekuError {
149 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
150 match *self {
151 DekuError::Incomplete(ref size) => write!(
152 f,
153 "Not enough data, need {} bits (or {} bytes)",
154 size.bit_size(),
155 size.byte_size()
156 ),
157 DekuError::Parse(ref err) => write!(f, "Parse error: {err}"),
158 DekuError::InvalidParam(ref err) => write!(f, "Invalid param error: {err}"),
159 DekuError::Assertion(ref err) => write!(f, "{err}"),
160 DekuError::IdVariantNotFound => write!(f, "Could not resolve `id` for variant"),
161 DekuError::Io(ref e) => write!(f, "io errorr: {e:?}"),
162 }
163 }
164}
165
166#[cfg(not(feature = "std"))]
167impl core::error::Error for DekuError {}
168
169#[cfg(not(feature = "std"))]
170impl core::fmt::Display for DekuError {
171 fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
172 Ok(())
173 }
174}
175
176#[cfg(not(feature = "std"))]
177impl From<DekuError> for no_std_io::io::Error {
178 fn from(error: DekuError) -> Self {
179 use no_std_io::io;
180 match error {
181 DekuError::Incomplete(_) => {
182 io::Error::new(io::ErrorKind::UnexpectedEof, "Short message buffer")
183 }
184 DekuError::Parse(msg) => io::Error::new(io::ErrorKind::InvalidData, msg),
185 DekuError::InvalidParam(msg) => io::Error::new(io::ErrorKind::InvalidInput, msg),
186 DekuError::Assertion(msg) => io::Error::new(io::ErrorKind::InvalidData, msg),
187 DekuError::IdVariantNotFound => {
188 io::Error::new(io::ErrorKind::NotFound, "Variant not found for ID")
189 }
190 DekuError::Io(kind) => io::Error::new(kind, "IO failure during parsing"),
191 }
192 }
193}
194
195#[cfg(feature = "std")]
196impl std::error::Error for DekuError {
197 fn cause(&self) -> Option<&dyn std::error::Error> {
198 Some(self)
199 }
200}
201
202#[cfg(feature = "std")]
203impl From<DekuError> for std::io::Error {
204 fn from(error: DekuError) -> Self {
205 use std::io;
206 match error {
207 DekuError::Incomplete(_) => io::Error::new(io::ErrorKind::UnexpectedEof, error),
208 DekuError::Parse(_) => io::Error::new(io::ErrorKind::InvalidData, error),
209 DekuError::InvalidParam(_) => io::Error::new(io::ErrorKind::InvalidInput, error),
210 DekuError::Assertion(_) => io::Error::new(io::ErrorKind::InvalidData, error),
211 DekuError::IdVariantNotFound => io::Error::new(io::ErrorKind::NotFound, error),
212 DekuError::Io(e) => io::Error::new(e, error),
213 }
214 }
215}
216
217impl From<no_std_io::io::Error> for DekuError {
218 fn from(value: no_std_io::io::Error) -> Self {
219 DekuError::Io(value.kind())
220 }
221}