1use core::fmt;
10
11#[derive(Debug, Clone, PartialEq, Eq)]
13#[non_exhaustive]
14pub enum XrceError {
15 WriteOverflow {
17 needed: usize,
19 available: usize,
21 },
22 UnexpectedEof {
24 needed: usize,
26 offset: usize,
28 },
29 UnknownSubmessageId {
31 id: u8,
33 },
34 TruncatedSubmessageBody {
37 declared: u16,
39 available: usize,
41 },
42 TooManySubmessages {
45 limit: usize,
47 },
48 PayloadTooLarge {
51 limit: usize,
53 actual: usize,
55 },
56 UnalignedSubmessage {
59 offset: usize,
61 },
62 ValueOutOfRange {
64 message: &'static str,
66 },
67}
68
69impl fmt::Display for XrceError {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 match self {
72 Self::WriteOverflow { needed, available } => write!(
73 f,
74 "xrce write overflow: needed {needed}, available {available}"
75 ),
76 Self::UnexpectedEof { needed, offset } => {
77 write!(f, "xrce unexpected EOF: needed {needed} at offset {offset}")
78 }
79 Self::UnknownSubmessageId { id } => {
80 write!(f, "xrce unknown submessage id 0x{id:02x}")
81 }
82 Self::TruncatedSubmessageBody {
83 declared,
84 available,
85 } => write!(
86 f,
87 "xrce submessage body truncated: declared {declared}, available {available}"
88 ),
89 Self::TooManySubmessages { limit } => {
90 write!(f, "xrce too many submessages: limit {limit}")
91 }
92 Self::PayloadTooLarge { limit, actual } => {
93 write!(f, "xrce payload too large: limit {limit}, actual {actual}")
94 }
95 Self::UnalignedSubmessage { offset } => {
96 write!(f, "xrce submessage not 4-byte aligned at offset {offset}")
97 }
98 Self::ValueOutOfRange { message } => {
99 write!(f, "xrce value out of range: {message}")
100 }
101 }
102 }
103}
104
105#[cfg(feature = "std")]
106impl std::error::Error for XrceError {}
107
108#[cfg(test)]
109mod tests {
110 #![allow(clippy::expect_used, clippy::unwrap_used)]
111 use super::*;
112
113 #[cfg(feature = "alloc")]
114 extern crate alloc;
115 #[cfg(feature = "alloc")]
116 use alloc::format;
117
118 #[cfg(feature = "alloc")]
119 #[test]
120 fn write_overflow_display_includes_numbers() {
121 let e = XrceError::WriteOverflow {
122 needed: 16,
123 available: 4,
124 };
125 let s = format!("{e}");
126 assert!(s.contains("16") && s.contains("4"));
127 }
128
129 #[cfg(feature = "alloc")]
130 #[test]
131 fn unknown_submessage_id_display_uses_hex() {
132 let e = XrceError::UnknownSubmessageId { id: 0xAB };
133 let s = format!("{e}");
134 assert!(s.contains("ab"));
135 }
136
137 #[cfg(feature = "alloc")]
138 #[test]
139 fn truncated_body_display_includes_values() {
140 let e = XrceError::TruncatedSubmessageBody {
141 declared: 100,
142 available: 50,
143 };
144 let s = format!("{e}");
145 assert!(s.contains("100") && s.contains("50"));
146 }
147
148 #[cfg(feature = "alloc")]
149 #[test]
150 fn too_many_submessages_display_mentions_limit() {
151 let e = XrceError::TooManySubmessages { limit: 64 };
152 assert!(format!("{e}").contains("64"));
153 }
154
155 #[cfg(feature = "alloc")]
156 #[test]
157 fn payload_too_large_display_includes_both() {
158 let e = XrceError::PayloadTooLarge {
159 limit: 1024,
160 actual: 2048,
161 };
162 let s = format!("{e}");
163 assert!(s.contains("1024") && s.contains("2048"));
164 }
165
166 #[cfg(feature = "alloc")]
167 #[test]
168 fn unaligned_display_mentions_offset() {
169 let e = XrceError::UnalignedSubmessage { offset: 17 };
170 assert!(format!("{e}").contains("17"));
171 }
172}