Coverage Report

Created: 2026-09-19 07:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}