rmp/decode/
bytes.rs

1//! Implementation of the [Bytes] type
2
3use super::RmpRead;
4use crate::decode::RmpReadErr;
5use 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 :(
11pub enum BytesReadError {
12    /// Indicates that there were not enough bytes.
13    InsufficientBytes {
14        expected: usize,
15        actual: usize,
16        position: u64,
17    },
18}
19
20impl Display for BytesReadError {
21    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
22        match *self {
23            BytesReadError::InsufficientBytes { expected, actual, position } => {
24                write!(f, "Expected at least bytes {expected}, but only got {actual} (pos {position})")
25            }
26        }
27    }
28}
29#[cfg(feature = "std")]
30impl std::error::Error for BytesReadError {}
31impl 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)]
47pub 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}
55impl<'a> Bytes<'a> {
56    /// Wrap an existing bytes slice.
57    ///
58    /// This sets the internal position to zero.
59    #[inline]
60    #[must_use]
61    pub fn new(bytes: &'a [u8]) -> Self {
62        Bytes { bytes, current_position: 0 }
63    }
64    /// Get a reference to the remaining bytes in the buffer.
65    #[inline]
66    #[must_use]
67    pub fn remaining_slice(&self) -> &'a [u8] {
68        self.bytes
69    }
70    /// Return the position of the input buffer.
71    ///
72    /// This is not required for correctness, it only exists to help mimic
73    /// [`Cursor::position`](std::io::Cursor::position)
74    #[inline]
75    #[must_use]
76    pub fn position(&self) -> u64 {
77        self.current_position
78    }
79}
80impl<'a> From<&'a [u8]> for Bytes<'a> {
81    #[inline]
82    fn from(bytes: &'a [u8]) -> Self {
83        Bytes { bytes, current_position: 0 }
84    }
85}
86
87impl RmpRead for Bytes<'_> {
88    type Error = BytesReadError;
89
90    #[inline]
91    fn read_u8(&mut self) -> Result<u8, Self::Error> {
92        if let Some((&first, newly_remaining)) = self.bytes.split_first() {
93            self.bytes = newly_remaining;
94            self.current_position += 1;
95            Ok(first)
96        } else {
97            Err(BytesReadError::InsufficientBytes {
98                expected: 1,
99                actual: 0,
100                position: self.current_position,
101            })
102        }
103    }
104
105    #[inline]
106    fn read_exact_buf(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
107        let to_read = buf.len();
108        if to_read <= self.bytes.len() {
109            let (src, newly_remaining) = self.bytes.split_at(to_read);
110            self.bytes = newly_remaining;
111            self.current_position += to_read as u64;
112            buf.copy_from_slice(src);
113            Ok(())
114        } else {
115            Err(BytesReadError::InsufficientBytes {
116                expected: to_read,
117                actual: self.bytes.len(),
118                position: self.current_position,
119            })
120        }
121    }
122}
123
124#[cfg(not(feature = "std"))]
125impl<'a> RmpRead for &'a [u8] {
126    type Error = BytesReadError;
127
128    fn read_u8(&mut self) -> Result<u8, Self::Error> {
129        if let Some((&first, newly_remaining)) = self.split_first() {
130            *self = newly_remaining;
131            Ok(first)
132        } else {
133            Err(BytesReadError::InsufficientBytes {
134                expected: 1,
135                actual: 0,
136                position: 0,
137            })
138        }
139    }
140
141    fn read_exact_buf(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
142        let to_read = buf.len();
143        if to_read <= self.len() {
144            let (src, newly_remaining) = self.split_at(to_read);
145            *self = newly_remaining;
146            buf.copy_from_slice(src);
147            Ok(())
148        } else {
149            Err(BytesReadError::InsufficientBytes {
150                expected: to_read,
151                actual: self.len(),
152                position: 0,
153            })
154        }
155    }
156}