1use core::ops::{Bound, RangeBounds};
2
3#[cfg(any(feature = "std", feature = "alloc"))]
9pub use bytes::TryGetError as BufTryGetError;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17pub struct TryGetError {
18 pub requested: usize,
20
21 pub available: usize,
23}
24
25impl core::fmt::Display for TryGetError {
26 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
27 write!(
28 f,
29 "Not enough bytes remaining in buffer to read value (requested {} but only {} available)",
30 self.requested, self.available
31 )
32 }
33}
34
35impl core::error::Error for TryGetError {}
36
37#[cfg(any(feature = "std", feature = "alloc"))]
38impl From<bytes::TryGetError> for TryGetError {
39 fn from(value: bytes::TryGetError) -> Self {
40 Self {
41 requested: value.requested,
42 available: value.available,
43 }
44 }
45}
46
47#[cfg(any(feature = "std", feature = "alloc"))]
48impl From<TryGetError> for bytes::TryGetError {
49 fn from(value: TryGetError) -> Self {
50 Self {
51 requested: value.requested,
52 available: value.available,
53 }
54 }
55}
56
57#[cfg(feature = "std")]
58impl From<TryGetError> for std::io::Error {
59 fn from(value: TryGetError) -> Self {
60 std::io::Error::other(value)
61 }
62}
63
64#[derive(Debug, PartialEq, Eq)]
70pub struct TryPutError {
71 pub requested: usize,
73
74 pub available: usize,
76}
77
78impl core::fmt::Display for TryPutError {
79 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
80 write!(
81 f,
82 "Not enough bytes remaining in buffer to write value (requested {} but only {} available)",
83 self.requested, self.available
84 )
85 }
86}
87
88impl core::error::Error for TryPutError {}
89
90#[cfg(feature = "std")]
91impl From<TryPutError> for std::io::Error {
92 fn from(value: TryPutError) -> Self {
93 std::io::Error::other(value)
94 }
95}
96
97#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
101pub struct InvalidIntegerLength(pub usize);
102
103impl core::fmt::Display for InvalidIntegerLength {
104 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
105 write!(
106 f,
107 "invalid integer length: {} (must be less or equal to 8)",
108 self.0
109 )
110 }
111}
112
113impl core::error::Error for InvalidIntegerLength {}
114
115#[cfg(feature = "std")]
116impl From<InvalidIntegerLength> for std::io::Error {
117 fn from(value: InvalidIntegerLength) -> Self {
118 std::io::Error::new(std::io::ErrorKind::InvalidInput, value)
119 }
120}
121
122impl From<InvalidIntegerLength> for TryPutIntegerError {
123 fn from(value: InvalidIntegerLength) -> Self {
124 TryPutIntegerError::InvalidLength(value)
125 }
126}
127
128#[derive(Debug, PartialEq, Eq)]
134pub enum TryPutIntegerCheckedError {
135 InvalidLength(InvalidIntegerLength),
137 OutOfRange {
139 value: i128,
141 min: i128,
143 max: i128,
145 nbytes: usize,
147 },
148 NotEnoughSpace(TryPutError),
150}
151
152impl core::fmt::Display for TryPutIntegerCheckedError {
153 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
154 match self {
155 Self::InvalidLength(error) => error.fmt(f),
156 Self::OutOfRange {
157 value,
158 min,
159 max,
160 nbytes,
161 } => write!(
162 f,
163 "value {value} is out of range for a {nbytes}-byte integer ({min}..={max})"
164 ),
165 Self::NotEnoughSpace(error) => error.fmt(f),
166 }
167 }
168}
169
170impl core::error::Error for TryPutIntegerCheckedError {
171 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
172 match self {
173 Self::InvalidLength(error) => Some(error),
174 Self::OutOfRange { .. } => None,
175 Self::NotEnoughSpace(error) => Some(error),
176 }
177 }
178}
179
180impl From<InvalidIntegerLength> for TryPutIntegerCheckedError {
181 fn from(value: InvalidIntegerLength) -> Self {
182 Self::InvalidLength(value)
183 }
184}
185
186impl From<TryPutError> for TryPutIntegerCheckedError {
187 fn from(value: TryPutError) -> Self {
188 Self::NotEnoughSpace(value)
189 }
190}
191
192#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
194pub enum TryGetIntegerError {
195 NotEnoughBytes(TryGetError),
197 InvalidLength(InvalidIntegerLength),
199}
200
201impl core::fmt::Display for TryGetIntegerError {
202 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
203 match self {
204 Self::NotEnoughBytes(error) => error.fmt(f),
205 Self::InvalidLength(error) => error.fmt(f),
206 }
207 }
208}
209
210impl core::error::Error for TryGetIntegerError {
211 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
212 match self {
213 Self::NotEnoughBytes(error) => Some(error),
214 Self::InvalidLength(error) => Some(error),
215 }
216 }
217}
218
219impl From<TryGetError> for TryGetIntegerError {
220 fn from(value: TryGetError) -> Self {
221 Self::NotEnoughBytes(value)
222 }
223}
224
225impl From<InvalidIntegerLength> for TryGetIntegerError {
226 fn from(value: InvalidIntegerLength) -> Self {
227 Self::InvalidLength(value)
228 }
229}
230
231#[cfg(feature = "std")]
232impl From<TryGetIntegerError> for std::io::Error {
233 fn from(value: TryGetIntegerError) -> Self {
234 std::io::Error::other(value)
235 }
236}
237
238#[derive(Debug, PartialEq, Eq)]
244pub enum TryPutIntegerError {
245 NotEnoughSpace(TryPutError),
247 InvalidLength(InvalidIntegerLength),
249}
250
251impl core::fmt::Display for TryPutIntegerError {
252 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
253 match self {
254 Self::NotEnoughSpace(err) => write!(f, "{}", err),
255 Self::InvalidLength(len) => write!(f, "{}", len),
256 }
257 }
258}
259
260impl core::error::Error for TryPutIntegerError {}
261
262#[cfg(feature = "std")]
263impl From<TryPutIntegerError> for std::io::Error {
264 fn from(value: TryPutIntegerError) -> Self {
265 std::io::Error::other(value)
266 }
267}
268#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
270pub struct OutOfBounds {
271 pub requested: usize,
273 pub available: usize,
275}
276
277impl OutOfBounds {
278 #[inline]
280 pub const fn new(requested: usize, available: usize) -> Self {
281 Self {
282 requested,
283 available,
284 }
285 }
286}
287
288impl core::fmt::Display for OutOfBounds {
289 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
290 write!(
291 f,
292 "index out of bounds: requested {} but only {} available",
293 self.requested, self.available
294 )
295 }
296}
297
298impl core::error::Error for OutOfBounds {}
299
300#[cfg(feature = "std")]
301impl From<OutOfBounds> for std::io::Error {
302 fn from(value: OutOfBounds) -> Self {
303 std::io::Error::new(std::io::ErrorKind::InvalidInput, value)
304 }
305}
306
307#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
309pub struct RangeOutOfBounds {
310 pub start: usize,
312 pub end: usize,
314 pub available: usize,
316}
317
318impl RangeOutOfBounds {
319 #[inline]
321 pub const fn new(start: usize, end: usize, available: usize) -> Self {
322 Self {
323 start,
324 end,
325 available,
326 }
327 }
328}
329
330impl core::fmt::Display for RangeOutOfBounds {
331 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
332 write!(
333 f,
334 "range out of bounds: requested {}..{} but only {} available",
335 self.start, self.end, self.available
336 )
337 }
338}
339
340impl core::error::Error for RangeOutOfBounds {}
341
342#[derive(Debug, PartialEq, Eq)]
344pub enum ByteEditError {
345 Range(RangeOutOfBounds),
347 Capacity(TryPutError),
349}
350
351impl core::fmt::Display for ByteEditError {
352 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
353 match self {
354 Self::Range(error) => error.fmt(f),
355 Self::Capacity(error) => error.fmt(f),
356 }
357 }
358}
359
360impl core::error::Error for ByteEditError {
361 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
362 match self {
363 Self::Range(error) => Some(error),
364 Self::Capacity(error) => Some(error),
365 }
366 }
367}
368
369impl From<RangeOutOfBounds> for ByteEditError {
370 fn from(value: RangeOutOfBounds) -> Self {
371 Self::Range(value)
372 }
373}
374
375impl From<TryPutError> for ByteEditError {
376 fn from(value: TryPutError) -> Self {
377 Self::Capacity(value)
378 }
379}
380
381pub(crate) fn normalize_range(
384 range: impl RangeBounds<usize>,
385 len: usize,
386) -> Result<(usize, usize), RangeOutOfBounds> {
387 let start = match range.start_bound() {
388 Bound::Included(&n) => n,
389 Bound::Excluded(&n) => n
390 .checked_add(1)
391 .ok_or_else(|| RangeOutOfBounds::new(n, n, len))?,
392 Bound::Unbounded => 0,
393 };
394
395 let end = match range.end_bound() {
396 Bound::Included(&n) => n
397 .checked_add(1)
398 .ok_or_else(|| RangeOutOfBounds::new(start, n, len))?,
399 Bound::Excluded(&n) => n,
400 Bound::Unbounded => len,
401 };
402
403 if start > end || end > len {
404 return Err(RangeOutOfBounds::new(start, end, len));
405 }
406
407 Ok((start, end))
408}
409
410#[cfg(feature = "std")]
411impl From<RangeOutOfBounds> for std::io::Error {
412 fn from(value: RangeOutOfBounds) -> Self {
413 std::io::Error::new(std::io::ErrorKind::InvalidInput, value)
414 }
415}
416
417#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
419pub enum Utf8IndexError {
420 InvalidCharBoundary {
422 index: usize,
424 },
425 IndexOutOfBounds(OutOfBounds),
427 RangeOutOfBounds(RangeOutOfBounds),
429}
430
431impl core::fmt::Display for Utf8IndexError {
432 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
433 match self {
434 Self::InvalidCharBoundary { index } => {
435 write!(
436 f,
437 "index {} does not lie on a UTF-8 character boundary",
438 index
439 )
440 }
441 Self::IndexOutOfBounds(error) => error.fmt(f),
442 Self::RangeOutOfBounds(error) => error.fmt(f),
443 }
444 }
445}
446
447impl core::error::Error for Utf8IndexError {
448 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
449 match self {
450 Self::InvalidCharBoundary { .. } => None,
451 Self::IndexOutOfBounds(error) => Some(error),
452 Self::RangeOutOfBounds(error) => Some(error),
453 }
454 }
455}
456
457impl From<OutOfBounds> for Utf8IndexError {
458 fn from(value: OutOfBounds) -> Self {
459 Self::IndexOutOfBounds(value)
460 }
461}
462
463impl From<RangeOutOfBounds> for Utf8IndexError {
464 fn from(value: RangeOutOfBounds) -> Self {
465 Self::RangeOutOfBounds(value)
466 }
467}
468
469#[derive(Debug, PartialEq, Eq)]
471pub enum Utf8EditError {
472 Index(Utf8IndexError),
474 Capacity(TryPutError),
476}
477
478impl core::fmt::Display for Utf8EditError {
479 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
480 match self {
481 Self::Index(error) => error.fmt(f),
482 Self::Capacity(error) => error.fmt(f),
483 }
484 }
485}
486
487impl core::error::Error for Utf8EditError {
488 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
489 match self {
490 Self::Index(error) => Some(error),
491 Self::Capacity(error) => Some(error),
492 }
493 }
494}
495
496impl From<Utf8IndexError> for Utf8EditError {
497 fn from(value: Utf8IndexError) -> Self {
498 Self::Index(value)
499 }
500}
501
502impl From<TryPutError> for Utf8EditError {
503 fn from(value: TryPutError) -> Self {
504 Self::Capacity(value)
505 }
506}
507
508#[derive(Debug, PartialEq, Eq)]
510pub enum Utf8FormatError {
511 Capacity(TryPutError),
513 Formatter(core::fmt::Error),
515}
516
517impl core::fmt::Display for Utf8FormatError {
518 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
519 match self {
520 Self::Capacity(error) => error.fmt(f),
521 Self::Formatter(error) => error.fmt(f),
522 }
523 }
524}
525
526impl core::error::Error for Utf8FormatError {
527 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
528 match self {
529 Self::Capacity(error) => Some(error),
530 Self::Formatter(error) => Some(error),
531 }
532 }
533}
534
535impl From<TryPutError> for Utf8FormatError {
536 fn from(value: TryPutError) -> Self {
537 Self::Capacity(value)
538 }
539}
540
541impl From<core::fmt::Error> for Utf8FormatError {
542 fn from(value: core::fmt::Error) -> Self {
543 Self::Formatter(value)
544 }
545}
546
547#[cfg(feature = "std")]
548impl From<Utf8IndexError> for std::io::Error {
549 fn from(value: Utf8IndexError) -> Self {
550 std::io::Error::new(std::io::ErrorKind::InvalidInput, value)
551 }
552}
553
554#[derive(Debug)]
559pub struct FromUtf8Error<B> {
560 bytes: B,
561 error: core::str::Utf8Error,
562}
563
564impl<B> FromUtf8Error<B> {
565 #[inline]
566 pub(crate) const fn new(bytes: B, error: core::str::Utf8Error) -> Self {
567 Self { bytes, error }
568 }
569
570 #[inline]
572 pub const fn utf8_error(&self) -> core::str::Utf8Error {
573 self.error
574 }
575
576 #[inline]
578 pub fn into_bytes(self) -> B {
579 self.bytes
580 }
581}
582
583impl<B> FromUtf8Error<B>
584where
585 B: AsRef<[u8]>,
586{
587 #[inline]
589 pub fn as_bytes(&self) -> &[u8] {
590 self.bytes.as_ref()
591 }
592}
593
594impl<B> core::fmt::Display for FromUtf8Error<B> {
595 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
596 write!(f, "invalid UTF-8: {}", self.error)
597 }
598}
599
600impl<B: core::fmt::Debug> core::error::Error for FromUtf8Error<B> {
601 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
602 Some(&self.error)
603 }
604}
605
606#[cfg(feature = "std")]
607impl<B: core::fmt::Debug + Send + Sync + 'static> From<FromUtf8Error<B>> for std::io::Error {
608 fn from(value: FromUtf8Error<B>) -> Self {
609 std::io::Error::new(std::io::ErrorKind::InvalidData, value)
610 }
611}
612
613#[derive(Debug, PartialEq, Eq)]
616pub enum FromBytesError {
617 InvalidUtf8(core::str::Utf8Error),
619 TooLarge(TryPutError),
621}
622
623impl core::fmt::Display for FromBytesError {
624 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
625 match self {
626 Self::InvalidUtf8(e) => write!(f, "invalid UTF-8: {}", e),
627 Self::TooLarge(e) => write!(f, "{}", e),
628 }
629 }
630}
631
632impl core::error::Error for FromBytesError {}
633
634impl From<core::str::Utf8Error> for FromBytesError {
635 fn from(e: core::str::Utf8Error) -> Self {
636 Self::InvalidUtf8(e)
637 }
638}
639
640impl From<TryPutError> for FromBytesError {
641 fn from(e: TryPutError) -> Self {
642 Self::TooLarge(e)
643 }
644}
645
646#[cfg(feature = "std")]
647impl From<FromBytesError> for std::io::Error {
648 fn from(value: FromBytesError) -> Self {
649 std::io::Error::new(std::io::ErrorKind::InvalidInput, value)
650 }
651}