| //! Implementation of the [Bytes] type |
| |
| use core::fmt::{Display, Formatter}; |
| use crate::decode::RmpReadErr; |
| use super::RmpRead; |
| |
| /// Indicates that an error occurred reading from [Bytes] |
| #[derive(Debug)] |
| #[non_exhaustive] |
| // NOTE: We can't use thiserror because of no_std :( |
| pub enum BytesReadError { |
| /// Indicates that there were not enough bytes. |
| InsufficientBytes { |
| expected: usize, |
| actual: usize, |
| position: u64 |
| } |
| } |
| |
| impl Display for BytesReadError { |
| fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { |
| match *self { |
| BytesReadError::InsufficientBytes { expected, actual, position } => { |
| write!(f, "Expected at least bytes {}, but only got {} (pos {})", expected, actual, position) |
| } |
| } |
| } |
| } |
| #[cfg(feature = "std")] |
| impl std::error::Error for BytesReadError {} |
| impl RmpReadErr for BytesReadError {} |
| |
| /// A wrapper around `&[u8]` to read more efficiently. |
| /// |
| /// This has a specialized implementation of `RmpWrite` |
| /// and has error type [Infallible](core::convert::Infallible). |
| /// |
| /// This has the additional benefit of working on `#[no_std]` (unlike the builtin Read trait) |
| /// |
| /// See also [serde_bytes::Bytes](https://docs.rs/serde_bytes/0.11/serde_bytes/struct.Bytes.html) |
| /// |
| /// Unlike a plain `&[u8]` this also tracks an internal offset in the input (See [Self::position]). |
| /// |
| /// This is used for (limited) compatibility with [std::io::Cursor]. Unlike a [Cursor](std::io::Cursor) it does |
| /// not support mark/reset. |
| #[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] |
| pub struct Bytes<'a> { |
| /// The internal position of the input buffer. |
| /// |
| /// This is not required for correctness. |
| /// It is only used for error reporting (and to implement [Self::position]) |
| current_position: u64, |
| bytes: &'a [u8], |
| } |
| impl<'a> Bytes<'a> { |
| /// Wrap an existing bytes slice. |
| /// |
| /// This sets the internal position to zero. |
| #[inline] |
| pub fn new(bytes: &'a [u8]) -> Self { |
| Bytes { bytes, current_position: 0 } |
| } |
| /// Get a reference to the remaining bytes in the buffer. |
| #[inline] |
| pub fn remaining_slice(&self) -> &'a [u8] { |
| self.bytes |
| } |
| /// Return the position of the input buffer. |
| /// |
| /// This is not required for correctness, it only exists to help mimic |
| /// [Cursor::position](std::io::Cursor::position) |
| #[inline] |
| pub fn position(&self) -> u64 { |
| self.current_position |
| } |
| } |
| impl<'a> From<&'a [u8]> for Bytes<'a> { |
| #[inline] |
| fn from(bytes: &'a [u8]) -> Self { |
| Bytes { bytes, current_position: 0 } |
| } |
| } |
| |
| impl RmpRead for Bytes<'_> { |
| type Error = BytesReadError; |
| |
| #[inline] |
| fn read_u8(&mut self) -> Result<u8, Self::Error> { |
| if let Some((&first, newly_remaining)) = self.bytes.split_first() { |
| self.bytes = newly_remaining; |
| self.current_position += 1; |
| Ok(first) |
| } else { |
| Err(BytesReadError::InsufficientBytes { |
| expected: 1, |
| actual: 0, |
| position: self.current_position |
| }) |
| } |
| } |
| |
| #[inline] |
| fn read_exact_buf(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> { |
| let to_read = buf.len(); |
| if to_read <= self.bytes.len() { |
| let (src, newly_remaining) = self.bytes.split_at(to_read); |
| self.bytes = newly_remaining; |
| self.current_position += to_read as u64; |
| buf.copy_from_slice(src); |
| Ok(()) |
| } else { |
| Err(BytesReadError::InsufficientBytes { |
| expected: to_read, |
| actual: self.bytes.len(), |
| position: self.current_position |
| }) |
| } |
| } |
| } |
| |
| #[cfg(not(feature = "std"))] |
| impl<'a> RmpRead for &'a [u8] { |
| type Error = BytesReadError; |
| |
| fn read_u8(&mut self) -> Result<u8, Self::Error> { |
| if let Some((&first, newly_remaining)) = self.split_first() { |
| *self = newly_remaining; |
| Ok(first) |
| } else { |
| Err(BytesReadError::InsufficientBytes { |
| expected: 1, |
| actual: 0, |
| position: 0 |
| }) |
| } |
| } |
| |
| fn read_exact_buf(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> { |
| let to_read = buf.len(); |
| if to_read <= self.len() { |
| let (src, newly_remaining) = self.split_at(to_read); |
| *self = newly_remaining; |
| buf.copy_from_slice(src); |
| Ok(()) |
| } else { |
| Err(BytesReadError::InsufficientBytes { |
| expected: to_read, |
| actual: self.len(), |
| position: 0 |
| }) |
| } |
| } |
| } |