unbytes/
lib.rs

1#![doc=include_str!("../README.md")]
2#![cfg_attr(not(feature="std"), no_std)]
3#![warn(missing_docs)]
4
5mod decode;
6
7#[cfg(feature="maypanic")]
8mod maypanic;
9
10use core::ops::Add;
11#[cfg(feature="std")]
12use std::{error::Error, fmt::Display};
13
14use bytes::*;
15
16pub use decode::{Decode, DecodeEndian};
17
18#[cfg(feature="maypanic")]
19pub use maypanic::ReaderMayPanic;
20
21/// Panic-free forward-only cursor. See the [module level docs][crate].
22pub struct Reader {
23    index: usize,
24    inner: Bytes,
25}
26
27impl Reader {
28    /// Creates a new Reader from anything that implements `Into<Bytes>`.
29    /// 
30    /// This does not allocate by itself, but the `Into<Bytes>` implementation might.
31    pub fn new<T: Into<Bytes>>(bytes: T) -> Self {
32        Self {
33            index: 0,
34            inner: bytes.into(),
35        }
36    }
37
38    #[inline]
39    fn increment(&mut self, amt: usize) {
40        self.index = self.index.add(amt).min(self.inner.len())
41    }
42
43    /// Returns how many bytes have not been read.
44    #[inline]
45    pub fn remaining(&self) -> usize {
46        self.inner.len().saturating_sub(self.index)
47    }
48
49    /// Returns `true` if at least `len` many bytes are unread.
50    #[inline]
51    pub fn at_least(&self, len: usize) -> bool {
52        self.remaining() >= len
53    }
54
55    /// Returns how many bytes have been read so far.
56    #[inline]
57    pub fn consumed(&self) -> usize {
58        self.index
59    }
60
61    /// Skips `amt` bytes.
62    pub fn skip(&mut self, amt: usize) {
63        self.increment(amt)
64    }
65
66    /// Returns `true` if there is another byte to read and it is equal to `val`.
67    pub fn peek(&self, val: u8) -> bool {
68        if !self.at_least(1) { return false; }
69        self.inner[self.index + 1] == val
70    }
71
72    /// Returns the rest of the unread data, consuming the iterator.
73    /// 
74    /// **Special behavior:**
75    /// If there are no bytes left, the inner value will be dropped,
76    /// instead returning a Bytes pointing to a static, empty slice.
77    pub fn read_to_end(self) -> Bytes {
78        if self.index == self.inner.len() {
79            return Bytes::new()
80        }
81
82        self.inner.slice(self.index..)
83    } 
84
85    /// Returns a `Reader` that can read the next `len` bytes,
86    /// advancing the original cursor by the same amount.
87    pub fn subreader(&mut self, len: usize) -> Result<Self, EndOfInput> {
88        if len == 0 { return Err(EndOfInput); }
89        Ok(Self::new(self.read_bytes(len)?))
90    }
91
92    /// Reads a single byte. Identical to [`read_u8`](Self::read_u8).
93    pub fn read_byte(&mut self) -> Result<u8, EndOfInput> {
94        if !self.at_least(1) { return Err(EndOfInput); }
95        let r = self.inner[self.index];
96        self.increment(1);
97        return Ok(r);
98    }
99
100    /// Returns the next `len` bytes as a [`Bytes`], advancing the cursor.
101    pub fn read_bytes(&mut self, len: usize) -> Result<Bytes, EndOfInput> {
102        if !self.at_least(len) { return Err(EndOfInput); }
103        let old_idx = self.index;
104        self.increment(len);
105        Ok(self.inner.slice(old_idx..old_idx+len))
106    }
107
108    /// Returns the next `len` bytes as a slice, advancing the cursor.
109    /// The returned slice will always be of length `len`.
110    pub fn read_slice(&mut self, len: usize) -> Result<&[u8], EndOfInput> {
111        if !self.at_least(len) { return Err(EndOfInput); }
112        let old_idx = self.index;
113        self.increment(len);
114        Ok(&self.inner[old_idx..old_idx+len])
115    }
116
117    /// Returns an array of size `N`, advancing the cursor.
118    pub fn read_array<const N: usize>(&mut self) -> Result<[u8; N], EndOfInput> {
119        let slice = self.read_slice(N)?;
120        let mut array = [0u8; N];
121        array.copy_from_slice(slice);
122        Ok(array)
123    }
124
125    /// Attempts to read a value based on its `Decode` implementation.
126    pub fn read<T: Decode>(&mut self) -> Result<T, EndOfInput> {
127        T::decode(self)
128    }
129}
130
131impl AsMut<Reader> for Reader {
132    #[inline(always)]
133    fn as_mut(&mut self) -> &mut Reader {
134        self
135    }
136}
137
138#[cfg(feature="std")]
139impl std::io::Read for Reader {
140    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
141        let amt = self.remaining().min(buf.len());
142        if amt == 0 { return Ok(0) }
143        buf[..amt].copy_from_slice(self.read_slice(amt).unwrap());
144        Ok(0)
145    }
146}
147
148impl From<Bytes> for Reader {
149    #[inline]
150    fn from(value: Bytes) -> Self {
151        Self {
152            index: 0,
153            inner: value,
154        }
155    }
156}
157
158/// Error returned when the end of the cursor is reached.
159#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
160pub struct EndOfInput;
161
162#[cfg(feature="std")]
163impl Display for EndOfInput {
164    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165        f.write_str("end of input")
166    }
167}
168
169#[cfg(feature="std")]
170impl Error for EndOfInput {}
171
172#[test]
173fn static_slice_test() {
174    let slice: &'static [u8; 20] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
175    let bytes = Bytes::from_static(slice);
176
177    let mut reader = Reader::new(bytes.clone());
178    assert_eq!(slice, &*reader.read_bytes(20).unwrap());
179
180    let mut reader = Reader::new(bytes.clone());
181    assert_eq!(slice, reader.read_slice(20).unwrap());
182
183    let mut reader = Reader::new(bytes.clone());
184    assert_eq!(slice, &reader.read_array::<20>().unwrap());
185
186    let mut reader = Reader::new(bytes.clone());
187    assert_eq!(&[1,2,3,4,5], &*reader.read_bytes(5).unwrap());
188    assert_eq!(&[6,7,8,9,10], reader.read_slice(5).unwrap());
189    assert_eq!(&[11,12,13,14,15], &reader.read_array::<5>().unwrap());
190    assert_eq!(16, reader.read_byte().unwrap());
191
192    assert_eq!(reader.consumed(), 16);
193    assert_eq!(reader.remaining(), 4);
194    assert!(reader.at_least(4));
195}