1use crate::fields::SmppField;
2
3#[derive(Debug)]
5pub struct DecodeError {
6 kind: DecodeErrorKind,
7 #[cfg(feature = "verbose")]
8 source: Option<alloc::boxed::Box<DecodeErrorSource>>,
9}
10
11impl DecodeError {
12 #[inline]
13 pub const fn new(kind: DecodeErrorKind) -> Self {
14 #[cfg(feature = "verbose")]
15 return Self { kind, source: None };
16
17 #[cfg(not(feature = "verbose"))]
18 Self { kind }
19 }
20
21 #[inline]
22 #[cold]
23 #[cfg(feature = "verbose")]
24 #[cfg_attr(docsrs, doc(cfg(feature = "verbose")))]
25 pub fn with_source(mut self, field: SmppField, error: DecodeError) -> Self {
26 self.source = Some(alloc::boxed::Box::new(DecodeErrorSource { field, error }));
27 self
28 }
29
30 #[inline]
31 #[cold]
32 #[cfg(feature = "verbose")]
33 #[cfg_attr(docsrs, doc(cfg(feature = "verbose")))]
34 pub fn as_source(self, field: SmppField) -> DecodeError {
35 DecodeError::new(self.kind).with_source(field, self)
36 }
37
38 #[inline]
39 #[cfg(feature = "verbose")]
40 #[cfg_attr(docsrs, doc(cfg(feature = "verbose")))]
41 pub fn source(&self) -> Option<&DecodeErrorSource> {
42 self.source.as_deref()
43 }
44
45 #[inline]
46 pub const fn kind(&self) -> DecodeErrorKind {
47 self.kind
48 }
49
50 #[inline]
51 pub const fn unexpected_eof() -> Self {
52 Self::new(DecodeErrorKind::UnexpectedEof)
53 }
54
55 #[inline]
56 pub const fn c_octet_string_decode_error(error: COctetStringDecodeError) -> Self {
57 Self::new(DecodeErrorKind::COctetStringDecodeError(error))
58 }
59
60 #[inline]
61 pub const fn octet_string_decode_error(error: OctetStringDecodeError) -> Self {
62 Self::new(DecodeErrorKind::OctetStringDecodeError(error))
63 }
64
65 #[inline]
66 pub const fn unsupported_key(key: u32) -> Self {
67 Self::new(DecodeErrorKind::UnsupportedKey { key })
68 }
69
70 #[inline]
71 pub const fn too_many_elements(max: usize) -> Self {
72 Self::new(DecodeErrorKind::TooManyElements { max })
73 }
74
75 #[cfg(feature = "verbose")]
77 #[cfg_attr(docsrs, doc(cfg(feature = "verbose")))]
78 pub fn field_exists(&self, field: SmppField) -> bool {
79 if let Some(source) = &self.source {
80 if source.field == field {
81 return true;
82 }
83
84 return source.error.field_exists(field);
85 }
86
87 false
88 }
89}
90
91#[derive(Debug)]
93#[cfg(feature = "verbose")]
94#[cfg_attr(docsrs, doc(cfg(feature = "verbose")))]
95pub struct DecodeErrorSource {
96 field: SmppField,
97 error: DecodeError,
98}
99
100#[cfg(feature = "verbose")]
101impl DecodeErrorSource {
102 pub const fn field(&self) -> SmppField {
103 self.field
104 }
105
106 pub const fn error(&self) -> &DecodeError {
107 &self.error
108 }
109}
110
111#[derive(Debug, Copy, Clone)]
113#[non_exhaustive]
114pub enum DecodeErrorKind {
115 UnexpectedEof,
116 COctetStringDecodeError(COctetStringDecodeError),
117 OctetStringDecodeError(OctetStringDecodeError),
118 UnsupportedKey {
119 key: u32,
120 },
121 TooManyElements {
125 max: usize,
126 },
127}
128
129#[derive(Debug, Copy, Clone)]
131#[non_exhaustive]
132pub enum COctetStringDecodeError {
133 TooFewBytes { actual: usize, min: usize },
134 NotAscii,
135 NotNullTerminated,
136}
137
138#[derive(Debug, Copy, Clone)]
140#[non_exhaustive]
141pub enum OctetStringDecodeError {
142 TooManyBytes { actual: usize, max: usize },
143 TooFewBytes { actual: usize, min: usize },
144}
145
146#[cfg(feature = "verbose")]
147impl core::fmt::Display for DecodeErrorSource {
148 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
149 write!(f, "field: {:?}, error: {}", self.field, self.error)
150 }
151}
152
153#[cfg(feature = "verbose")]
154impl core::error::Error for DecodeErrorSource {
155 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
156 Some(&self.error)
157 }
158
159 fn cause(&self) -> Option<&dyn core::error::Error> {
160 self.source()
161 }
162}
163
164impl core::fmt::Display for DecodeError {
165 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
166 #[cfg(feature = "verbose")]
167 return match &self.source {
168 Some(source) => {
169 write!(f, "Decode error. kind: {}, source: [{source}]", self.kind,)
170 }
171 None => write!(f, "Decode error. kind: {}", self.kind),
172 };
173
174 #[cfg(not(feature = "verbose"))]
175 write!(f, "Decode error. kind: {}", self.kind)
176 }
177}
178
179impl core::error::Error for DecodeError {
180 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
181 #[cfg(feature = "verbose")]
182 return match &self.source {
183 Some(source) => Some(source.as_ref()),
184 None => None,
185 };
186
187 #[cfg(not(feature = "verbose"))]
188 None
189 }
190
191 fn cause(&self) -> Option<&dyn core::error::Error> {
192 core::error::Error::source(self)
193 }
194}
195
196impl core::fmt::Display for DecodeErrorKind {
197 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
198 match self {
199 DecodeErrorKind::UnexpectedEof => write!(f, "Unexpected EOF"),
200 DecodeErrorKind::COctetStringDecodeError(e) => write!(f, "COctetString error: {e}"),
201 DecodeErrorKind::OctetStringDecodeError(e) => write!(f, "OctetString error: {e}"),
202 DecodeErrorKind::UnsupportedKey { key } => write!(f, "Unsupported key: {key}"),
203 DecodeErrorKind::TooManyElements { max } => {
204 write!(f, "Too many elements. max: {max}")
205 }
206 }
207 }
208}
209
210impl core::fmt::Display for COctetStringDecodeError {
211 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
212 match self {
213 COctetStringDecodeError::TooFewBytes { actual, min } => {
214 write!(f, "Too few bytes. actual: {actual}, min: {min}")
215 }
216 COctetStringDecodeError::NotAscii => write!(f, "Not ASCII"),
217 COctetStringDecodeError::NotNullTerminated => write!(f, "Not null terminated"),
218 }
219 }
220}
221
222impl core::error::Error for COctetStringDecodeError {}
223
224impl core::fmt::Display for OctetStringDecodeError {
225 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
226 match self {
227 OctetStringDecodeError::TooManyBytes { actual, max } => {
228 write!(f, "Too many bytes. actual: {actual}, max: {max}")
229 }
230 OctetStringDecodeError::TooFewBytes { actual, min } => {
231 write!(f, "Too few bytes. actual: {actual}, min: {min}")
232 }
233 }
234 }
235}
236
237impl core::error::Error for OctetStringDecodeError {}
238
239#[doc(hidden)]
240pub trait DecodeResultExt<T, E> {
241 fn map_decoded<F, U>(self, op: F) -> Result<(U, usize), E>
242 where
243 F: FnOnce(T) -> U;
244}
245
246impl<T, E> DecodeResultExt<T, E> for Result<(T, usize), E> {
247 fn map_decoded<F, U>(self, op: F) -> Result<(U, usize), E>
248 where
249 F: FnOnce(T) -> U,
250 {
251 self.map(|(this, size)| (op(this), size))
252 }
253}
254
255#[doc(hidden)]
256pub trait DecodeErrorExt<T> {
257 fn map_as_source(self, field: SmppField) -> Result<T, DecodeError>;
258}
259
260impl<T> DecodeErrorExt<T> for Result<T, DecodeError> {
261 #[cold]
262 fn map_as_source(self, _field: SmppField) -> Result<T, DecodeError> {
263 #[cfg(feature = "verbose")]
264 return self.map_err(|error| error.as_source(_field));
265
266 #[cfg(not(feature = "verbose"))]
267 self
268 }
269}