1use core::ops::{Bound, RangeBounds};
2
3#[cfg(any(feature = "std", feature = "alloc"))]
4pub use bytes::TryGetError;
5
6#[derive(Debug, PartialEq, Eq)]
12#[cfg(not(any(feature = "std", feature = "alloc")))]
13pub struct TryGetError {
14 pub requested: usize,
16
17 pub available: usize,
19}
20
21#[cfg(not(any(feature = "std", feature = "alloc")))]
22const _: () = {
23 impl core::fmt::Display for TryGetError {
24 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
25 write!(
26 f,
27 "Not enough bytes remaining in buffer to read value (requested {} but only {} available)",
28 self.requested, self.available
29 )
30 }
31 }
32
33 impl core::error::Error for TryGetError {}
34};
35
36#[derive(Debug, PartialEq, Eq)]
42pub struct TryPutError {
43 pub requested: usize,
45
46 pub available: usize,
48}
49
50impl core::fmt::Display for TryPutError {
51 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
52 write!(
53 f,
54 "Not enough bytes remaining in buffer to write value (requested {} but only {} available)",
55 self.requested, self.available
56 )
57 }
58}
59
60impl core::error::Error for TryPutError {}
61
62#[cfg(feature = "std")]
63impl From<TryPutError> for std::io::Error {
64 fn from(value: TryPutError) -> Self {
65 std::io::Error::other(value)
66 }
67}
68
69#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
73pub struct InvalidIntegerLength(pub usize);
74
75impl core::fmt::Display for InvalidIntegerLength {
76 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
77 write!(
78 f,
79 "invalid integer length: {} (must be less or equal to 8)",
80 self.0
81 )
82 }
83}
84
85impl core::error::Error for InvalidIntegerLength {}
86
87#[cfg(feature = "std")]
88impl From<InvalidIntegerLength> for std::io::Error {
89 fn from(value: InvalidIntegerLength) -> Self {
90 std::io::Error::new(std::io::ErrorKind::InvalidInput, value)
91 }
92}
93
94impl From<InvalidIntegerLength> for TryPutIntegerError {
95 fn from(value: InvalidIntegerLength) -> Self {
96 TryPutIntegerError::InvalidLength(value)
97 }
98}
99
100#[derive(Debug, PartialEq, Eq)]
106pub enum TryPutIntegerError {
107 NotEnoughSpace(TryPutError),
109 InvalidLength(InvalidIntegerLength),
111}
112
113impl core::fmt::Display for TryPutIntegerError {
114 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
115 match self {
116 Self::NotEnoughSpace(err) => write!(f, "{}", err),
117 Self::InvalidLength(len) => write!(f, "{}", len),
118 }
119 }
120}
121
122impl core::error::Error for TryPutIntegerError {}
123
124#[cfg(feature = "std")]
125impl From<TryPutIntegerError> for std::io::Error {
126 fn from(value: TryPutIntegerError) -> Self {
127 std::io::Error::other(value)
128 }
129}
130#[derive(Debug, Clone, Copy, PartialEq, Eq)]
132pub struct OutOfBounds {
133 pub requested: usize,
135 pub available: usize,
137}
138
139impl OutOfBounds {
140 #[inline]
142 pub const fn new(requested: usize, available: usize) -> Self {
143 Self {
144 requested,
145 available,
146 }
147 }
148}
149
150impl core::fmt::Display for OutOfBounds {
151 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
152 write!(
153 f,
154 "index out of bounds: requested {} but only {} available",
155 self.requested, self.available
156 )
157 }
158}
159
160impl core::error::Error for OutOfBounds {}
161
162#[cfg(feature = "std")]
163impl From<OutOfBounds> for std::io::Error {
164 fn from(value: OutOfBounds) -> Self {
165 std::io::Error::new(std::io::ErrorKind::InvalidInput, value)
166 }
167}
168
169#[derive(Debug, Clone, Copy, PartialEq, Eq)]
171pub struct RangeOutOfBounds {
172 pub start: usize,
174 pub end: usize,
176 pub available: usize,
178}
179
180impl RangeOutOfBounds {
181 #[inline]
183 pub const fn new(start: usize, end: usize, available: usize) -> Self {
184 Self {
185 start,
186 end,
187 available,
188 }
189 }
190}
191
192impl core::fmt::Display for RangeOutOfBounds {
193 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
194 write!(
195 f,
196 "range out of bounds: requested {}..{} but only {} available",
197 self.start, self.end, self.available
198 )
199 }
200}
201
202impl core::error::Error for RangeOutOfBounds {}
203
204pub(crate) fn normalize_range(
207 range: impl RangeBounds<usize>,
208 len: usize,
209) -> Result<(usize, usize), RangeOutOfBounds> {
210 let start = match range.start_bound() {
211 Bound::Included(&n) => n,
212 Bound::Excluded(&n) => n
213 .checked_add(1)
214 .ok_or_else(|| RangeOutOfBounds::new(n, n, len))?,
215 Bound::Unbounded => 0,
216 };
217
218 let end = match range.end_bound() {
219 Bound::Included(&n) => n
220 .checked_add(1)
221 .ok_or_else(|| RangeOutOfBounds::new(start, n, len))?,
222 Bound::Excluded(&n) => n,
223 Bound::Unbounded => len,
224 };
225
226 if start > end || end > len {
227 return Err(RangeOutOfBounds::new(start, end, len));
228 }
229
230 Ok((start, end))
231}
232
233#[cfg(feature = "std")]
234impl From<RangeOutOfBounds> for std::io::Error {
235 fn from(value: RangeOutOfBounds) -> Self {
236 std::io::Error::new(std::io::ErrorKind::InvalidInput, value)
237 }
238}
239
240#[derive(Debug, Clone, Copy, PartialEq, Eq)]
243pub enum Utf8Error {
244 InvalidCharBoundary {
246 at: usize,
248 },
249 OutOfBounds {
251 at: usize,
253 len: usize,
255 },
256}
257
258impl core::fmt::Display for Utf8Error {
259 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
260 match self {
261 Self::InvalidCharBoundary { at } => {
262 write!(f, "index {} does not lie on a UTF-8 character boundary", at)
263 }
264 Self::OutOfBounds { at, len } => {
265 write!(f, "index {} out of bounds: length is {}", at, len)
266 }
267 }
268 }
269}
270
271impl core::error::Error for Utf8Error {}
272
273#[cfg(feature = "std")]
274impl From<Utf8Error> for std::io::Error {
275 fn from(value: Utf8Error) -> Self {
276 std::io::Error::new(std::io::ErrorKind::InvalidInput, value)
277 }
278}
279
280#[derive(Debug, PartialEq, Eq)]
283pub enum FromBytesError {
284 InvalidUtf8(core::str::Utf8Error),
286 TooLarge(TryPutError),
288}
289
290impl core::fmt::Display for FromBytesError {
291 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
292 match self {
293 Self::InvalidUtf8(e) => write!(f, "invalid UTF-8: {}", e),
294 Self::TooLarge(e) => write!(f, "{}", e),
295 }
296 }
297}
298
299impl core::error::Error for FromBytesError {}
300
301impl From<core::str::Utf8Error> for FromBytesError {
302 fn from(e: core::str::Utf8Error) -> Self {
303 Self::InvalidUtf8(e)
304 }
305}
306
307impl From<TryPutError> for FromBytesError {
308 fn from(e: TryPutError) -> Self {
309 Self::TooLarge(e)
310 }
311}
312
313#[cfg(feature = "std")]
314impl From<FromBytesError> for std::io::Error {
315 fn from(value: FromBytesError) -> Self {
316 std::io::Error::new(std::io::ErrorKind::InvalidInput, value)
317 }
318}