bincode/de/read.rs
1//! This module contains reader-based structs and traits.
2//!
3//! Because `std::io::Read` is only limited to `std` and not `core`, we provide 2 alternative readers.
4//!
5//! [Reader] is a reader for sources that do not own their data. It is assumed that the reader's data is dropped after the `read` method is called. This reader is incapable of reading borrowed data, like `&str` and `&[u8]`.
6//!
7//! [BorrowReader] is an extension of `Reader` that also allows returning borrowed data. A `BorrowReader` allows reading `&str` and `&[u8]`.
8//!
9//! Specifically the `Reader` trait is used by [Decode] and the `BorrowReader` trait is used by `[BorrowDecode]`.
10//!
11//! [Decode]: ../trait.Decode.html
12//! [BorrowDecode]: ../trait.BorrowDecode.html
13
14use crate::error::DecodeError;
15
16/// A reader for owned data. See the module documentation for more information.
17pub trait Reader {
18 /// Fill the given `bytes` argument with values. Exactly the length of the given slice must be filled, or else an error must be returned.
19 fn read(&mut self, bytes: &mut [u8]) -> Result<(), DecodeError>;
20
21 /// If this reader wraps a buffer of any kind, this function lets callers access contents of
22 /// the buffer without passing data through a buffer first.
23 #[inline]
24 fn peek_read(&mut self, _: usize) -> Option<&[u8]> {
25 None
26 }
27
28 /// If an implementation of `peek_read` is provided, an implementation of this function
29 /// must be provided so that subsequent reads or peek-reads do not return the same bytes
30 #[inline]
31 fn consume(&mut self, _: usize) {}
32}
33
34impl<T> Reader for &mut T
35where
36 T: Reader,
37{
38 #[inline]
39 fn read(&mut self, bytes: &mut [u8]) -> Result<(), DecodeError> {
40 (**self).read(bytes)
41 }
42
43 #[inline]
44 fn peek_read(&mut self, n: usize) -> Option<&[u8]> {
45 (**self).peek_read(n)
46 }
47
48 #[inline]
49 fn consume(&mut self, n: usize) {
50 (*self).consume(n)
51 }
52}
53
54/// A reader for borrowed data. Implementors of this must also implement the [Reader] trait. See the module documentation for more information.
55pub trait BorrowReader<'storage>: Reader {
56 /// Read exactly `length` bytes and return a slice to this data. If not enough bytes could be read, an error should be returned.
57 ///
58 /// *note*: Exactly `length` bytes must be returned. If less bytes are returned, bincode may panic. If more bytes are returned, the excess bytes may be discarded.
59 fn take_bytes(&mut self, length: usize) -> Result<&'storage [u8], DecodeError>;
60}
61
62/// A reader type for `&[u8]` slices. Implements both [Reader] and [BorrowReader], and thus can be used for borrowed data.
63pub struct SliceReader<'storage> {
64 pub(crate) slice: &'storage [u8],
65}
66
67impl<'storage> SliceReader<'storage> {
68 /// Constructs a slice reader
69 pub const fn new(bytes: &'storage [u8]) -> SliceReader<'storage> {
70 SliceReader { slice: bytes }
71 }
72}
73
74impl<'storage> Reader for SliceReader<'storage> {
75 #[inline(always)]
76 fn read(&mut self, bytes: &mut [u8]) -> Result<(), DecodeError> {
77 if bytes.len() > self.slice.len() {
78 return Err(DecodeError::UnexpectedEnd {
79 additional: bytes.len() - self.slice.len(),
80 });
81 }
82 let (read_slice, remaining) = self.slice.split_at(bytes.len());
83 bytes.copy_from_slice(read_slice);
84 self.slice = remaining;
85
86 Ok(())
87 }
88
89 #[inline]
90 fn peek_read(&mut self, n: usize) -> Option<&'storage [u8]> {
91 self.slice.get(..n)
92 }
93
94 #[inline]
95 fn consume(&mut self, n: usize) {
96 self.slice = self.slice.get(n..).unwrap_or_default();
97 }
98}
99
100impl<'storage> BorrowReader<'storage> for SliceReader<'storage> {
101 #[inline(always)]
102 fn take_bytes(&mut self, length: usize) -> Result<&'storage [u8], DecodeError> {
103 if length > self.slice.len() {
104 return Err(DecodeError::UnexpectedEnd {
105 additional: length - self.slice.len(),
106 });
107 }
108 let (read_slice, remaining) = self.slice.split_at(length);
109 self.slice = remaining;
110 Ok(read_slice)
111 }
112}