/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rmp-0.8.15/src/decode/bytes.rs
Line | Count | Source |
1 | | //! Implementation of the [Bytes] type |
2 | | |
3 | | use super::RmpRead; |
4 | | use crate::decode::RmpReadErr; |
5 | | use core::fmt::{Display, Formatter}; |
6 | | |
7 | | /// Indicates that an error occurred reading from [Bytes] |
8 | | #[derive(Debug)] |
9 | | #[non_exhaustive] |
10 | | // NOTE: We can't use thiserror because of no_std :( |
11 | | pub enum BytesReadError { |
12 | | /// Indicates that there were not enough bytes. |
13 | | InsufficientBytes { |
14 | | expected: usize, |
15 | | actual: usize, |
16 | | position: u64, |
17 | | }, |
18 | | } |
19 | | |
20 | | impl Display for BytesReadError { |
21 | 0 | fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { |
22 | 0 | match *self { |
23 | 0 | Self::InsufficientBytes { expected, actual, position } => { |
24 | 0 | write!(f, "Expected at least bytes {expected}, but only got {actual} (pos {position})") |
25 | | }, |
26 | | } |
27 | 0 | } |
28 | | } |
29 | | #[cfg(feature = "std")] |
30 | | impl std::error::Error for BytesReadError {} |
31 | | impl RmpReadErr for BytesReadError {} |
32 | | |
33 | | /// A wrapper around `&[u8]` to read more efficiently. |
34 | | /// |
35 | | /// This has a specialized implementation of `RmpWrite` |
36 | | /// and has error type [Infallible](core::convert::Infallible). |
37 | | /// |
38 | | /// This has the additional benefit of working on `#[no_std]` (unlike the builtin Read trait) |
39 | | /// |
40 | | /// See also [serde_bytes::Bytes](https://docs.rs/serde_bytes/0.11/serde_bytes/struct.Bytes.html) |
41 | | /// |
42 | | /// Unlike a plain `&[u8]` this also tracks an internal offset in the input (See [`Self::position`]). |
43 | | /// |
44 | | /// This is used for (limited) compatibility with [`std::io::Cursor`]. Unlike a [Cursor](std::io::Cursor) it does |
45 | | /// not support mark/reset. |
46 | | #[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] |
47 | | pub struct Bytes<'a> { |
48 | | /// The internal position of the input buffer. |
49 | | /// |
50 | | /// This is not required for correctness. |
51 | | /// It is only used for error reporting (and to implement [`Self::position`]) |
52 | | current_position: u64, |
53 | | bytes: &'a [u8], |
54 | | } |
55 | | impl<'a> Bytes<'a> { |
56 | | /// Wrap an existing bytes slice. |
57 | | /// |
58 | | /// This sets the internal position to zero. |
59 | | #[inline] |
60 | | #[must_use] |
61 | 0 | pub const fn new(bytes: &'a [u8]) -> Self { |
62 | 0 | Bytes { bytes, current_position: 0 } |
63 | 0 | } |
64 | | |
65 | | /// Get a reference to the remaining bytes in the buffer. |
66 | | #[inline] |
67 | | #[must_use] |
68 | 0 | pub const fn remaining_slice(&self) -> &'a [u8] { |
69 | 0 | self.bytes |
70 | 0 | } |
71 | | |
72 | | /// Return the position of the input buffer. |
73 | | /// |
74 | | /// This is not required for correctness, it only exists to help mimic |
75 | | /// [`Cursor::position`](std::io::Cursor::position) |
76 | | #[inline] |
77 | | #[must_use] |
78 | 0 | pub const fn position(&self) -> u64 { |
79 | 0 | self.current_position |
80 | 0 | } |
81 | | } |
82 | | impl<'a> From<&'a [u8]> for Bytes<'a> { |
83 | | #[inline] |
84 | 0 | fn from(bytes: &'a [u8]) -> Self { |
85 | 0 | Bytes { bytes, current_position: 0 } |
86 | 0 | } |
87 | | } |
88 | | |
89 | | impl RmpRead for Bytes<'_> { |
90 | | type Error = BytesReadError; |
91 | | |
92 | | #[inline] |
93 | 0 | fn read_u8(&mut self) -> Result<u8, Self::Error> { |
94 | 0 | if let Some((&first, newly_remaining)) = self.bytes.split_first() { |
95 | 0 | self.bytes = newly_remaining; |
96 | 0 | self.current_position += 1; |
97 | 0 | Ok(first) |
98 | | } else { |
99 | 0 | Err(BytesReadError::InsufficientBytes { |
100 | 0 | expected: 1, |
101 | 0 | actual: 0, |
102 | 0 | position: self.current_position, |
103 | 0 | }) |
104 | | } |
105 | 0 | } |
106 | | |
107 | | #[inline] |
108 | 0 | fn read_exact_buf(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> { |
109 | 0 | let to_read = buf.len(); |
110 | 0 | if to_read <= self.bytes.len() { |
111 | 0 | let (src, newly_remaining) = self.bytes.split_at(to_read); |
112 | 0 | self.bytes = newly_remaining; |
113 | 0 | self.current_position += to_read as u64; |
114 | 0 | buf.copy_from_slice(src); |
115 | 0 | Ok(()) |
116 | | } else { |
117 | 0 | Err(BytesReadError::InsufficientBytes { |
118 | 0 | expected: to_read, |
119 | 0 | actual: self.bytes.len(), |
120 | 0 | position: self.current_position, |
121 | 0 | }) |
122 | | } |
123 | 0 | } |
124 | | } |
125 | | |
126 | | #[cfg(not(feature = "std"))] |
127 | | impl<'a> RmpRead for &'a [u8] { |
128 | | type Error = BytesReadError; |
129 | | |
130 | | fn read_u8(&mut self) -> Result<u8, Self::Error> { |
131 | | if let Some((&first, newly_remaining)) = self.split_first() { |
132 | | *self = newly_remaining; |
133 | | Ok(first) |
134 | | } else { |
135 | | Err(BytesReadError::InsufficientBytes { |
136 | | expected: 1, |
137 | | actual: 0, |
138 | | position: 0, |
139 | | }) |
140 | | } |
141 | | } |
142 | | |
143 | | fn read_exact_buf(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> { |
144 | | let to_read = buf.len(); |
145 | | if to_read <= self.len() { |
146 | | let (src, newly_remaining) = self.split_at(to_read); |
147 | | *self = newly_remaining; |
148 | | buf.copy_from_slice(src); |
149 | | Ok(()) |
150 | | } else { |
151 | | Err(BytesReadError::InsufficientBytes { |
152 | | expected: to_read, |
153 | | actual: self.len(), |
154 | | position: 0, |
155 | | }) |
156 | | } |
157 | | } |
158 | | } |