Skip to main content

float_pigment_consistent_bincode/de/
read.rs

1use crate::error::Result;
2use crate::io;
3use alloc::{boxed::Box, vec::Vec};
4
5/// An optional Read trait for advanced Bincode usage.
6///
7/// It is highly recommended to use bincode with `io::Read` or `&[u8]` before
8/// implementing a custom `BincodeRead`.
9///
10/// The forward_read_* methods are necessary because some byte sources want
11/// to pass a long-lived borrow to the visitor and others want to pass a
12/// transient slice.
13pub trait BincodeRead<'storage>: io::Read {
14    /// Check that the next `length` bytes are a valid string and pass
15    /// it on to the serde reader.
16    fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
17    where
18        V: serde::de::Visitor<'storage>;
19
20    /// Transfer ownership of the next `length` bytes to the caller.
21    fn get_byte_buffer(&mut self, length: usize) -> Result<Vec<u8>>;
22
23    /// Pass a slice of the next `length` bytes on to the serde reader.
24    fn forward_read_bytes<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
25    where
26        V: serde::de::Visitor<'storage>;
27
28    /// Get the current barrier offset.
29    fn barrier(&self) -> usize;
30
31    /// Set the barrier to prevent reading beyond.
32    fn set_barrier(&mut self, offset: usize);
33
34    /// Skip remaining bytes before the current barrier.
35    fn forward_to_barrier(&mut self) -> io::Result<()>;
36}
37
38/// A BincodeRead implementation for byte slices
39pub struct SliceReader<'storage> {
40    slice: &'storage [u8],
41    barrier_offset: usize,
42}
43
44/// A BincodeRead implementation for `io::Read`ers
45pub struct IoReader<R> {
46    reader: R,
47    temp_buffer: Vec<u8>,
48    barrier_offset: usize,
49}
50
51impl<'storage> SliceReader<'storage> {
52    /// Constructs a slice reader
53    pub(crate) fn new(bytes: &'storage [u8]) -> SliceReader<'storage> {
54        SliceReader {
55            slice: bytes,
56            barrier_offset: core::usize::MAX,
57        }
58    }
59
60    #[inline(always)]
61    fn get_byte_slice(&mut self, length: usize) -> Result<&'storage [u8]> {
62        if self.barrier_offset < length {
63            self.forward_to_barrier()?;
64            Err(crate::ErrorKind::SegmentEnded)?;
65        }
66        self.barrier_offset -= length;
67        if length > self.slice.len() {
68            return Err(SliceReader::unexpected_eof());
69        }
70        let (read_slice, remaining) = self.slice.split_at(length);
71        self.slice = remaining;
72        Ok(read_slice)
73    }
74
75    pub(crate) fn is_finished(&self) -> bool {
76        self.slice.is_empty()
77    }
78}
79
80impl<R> IoReader<R> {
81    /// Constructs an IoReadReader
82    pub(crate) fn new(r: R) -> IoReader<R> {
83        IoReader {
84            reader: r,
85            temp_buffer: vec![],
86            barrier_offset: core::usize::MAX,
87        }
88    }
89}
90
91impl<'storage> io::Read for SliceReader<'storage> {
92    #[inline(always)]
93    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
94        if self.barrier_offset < out.len() {
95            self.forward_to_barrier()?;
96            return Err(io::ErrorKind::UnexpectedEof.into());
97        }
98        self.barrier_offset -= out.len();
99        if out.len() > self.slice.len() {
100            return Err(io::ErrorKind::UnexpectedEof.into());
101        }
102        let (read_slice, remaining) = self.slice.split_at(out.len());
103        out.copy_from_slice(read_slice);
104        self.slice = remaining;
105
106        Ok(out.len())
107    }
108
109    #[inline(always)]
110    fn read_exact(&mut self, out: &mut [u8]) -> io::Result<()> {
111        self.read(out).map(|_| ())
112    }
113}
114
115impl<R: io::Read> io::Read for IoReader<R> {
116    #[inline(always)]
117    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
118        if self.barrier_offset < out.len() {
119            self.forward_to_barrier()?;
120            return Err(io::ErrorKind::UnexpectedEof.into());
121        }
122        self.barrier_offset -= out.len();
123        self.reader.read(out)
124    }
125    #[inline(always)]
126    fn read_exact(&mut self, out: &mut [u8]) -> io::Result<()> {
127        if self.barrier_offset < out.len() {
128            self.forward_to_barrier()?;
129            return Err(io::ErrorKind::UnexpectedEof.into());
130        }
131        self.barrier_offset -= out.len();
132        self.reader.read_exact(out)
133    }
134}
135
136impl<'storage> SliceReader<'storage> {
137    #[inline(always)]
138    fn unexpected_eof() -> Box<crate::ErrorKind> {
139        Box::new(crate::ErrorKind::Io(io::Error::new(
140            io::ErrorKind::UnexpectedEof,
141        )))
142    }
143}
144
145impl<'storage> BincodeRead<'storage> for SliceReader<'storage> {
146    #[inline(always)]
147    fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
148    where
149        V: serde::de::Visitor<'storage>,
150    {
151        use crate::ErrorKind;
152        let string = match ::core::str::from_utf8(self.get_byte_slice(length)?) {
153            Ok(s) => s,
154            Err(e) => return Err(ErrorKind::InvalidUtf8Encoding(e).into()),
155        };
156        visitor.visit_borrowed_str(string)
157    }
158
159    #[inline(always)]
160    fn get_byte_buffer(&mut self, length: usize) -> Result<Vec<u8>> {
161        self.get_byte_slice(length).map(|x| x.to_vec())
162    }
163
164    #[inline(always)]
165    fn forward_read_bytes<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
166    where
167        V: serde::de::Visitor<'storage>,
168    {
169        visitor.visit_borrowed_bytes(self.get_byte_slice(length)?)
170    }
171
172    #[inline(always)]
173    fn barrier(&self) -> usize {
174        self.barrier_offset
175    }
176
177    #[inline(always)]
178    fn set_barrier(&mut self, offset: usize) {
179        self.barrier_offset = offset;
180    }
181
182    #[inline(always)]
183    fn forward_to_barrier(&mut self) -> io::Result<()> {
184        let (_, remaining) = self.slice.split_at(self.barrier_offset);
185        self.slice = remaining;
186        self.barrier_offset = 0;
187        Ok(())
188    }
189}
190
191impl<R> IoReader<R>
192where
193    R: io::Read,
194{
195    fn fill_buffer(&mut self, length: usize) -> Result<()> {
196        if self.barrier_offset < length {
197            self.forward_to_barrier()?;
198            Err(crate::ErrorKind::SegmentEnded)?;
199        }
200        self.barrier_offset -= length;
201
202        self.temp_buffer.resize(length, 0);
203
204        self.reader.read_exact(&mut self.temp_buffer)?;
205
206        Ok(())
207    }
208}
209
210impl<'a, R> BincodeRead<'a> for IoReader<R>
211where
212    R: io::Read,
213{
214    fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
215    where
216        V: serde::de::Visitor<'a>,
217    {
218        self.fill_buffer(length)?;
219
220        let string = match ::core::str::from_utf8(&self.temp_buffer[..]) {
221            Ok(s) => s,
222            Err(e) => return Err(crate::ErrorKind::InvalidUtf8Encoding(e).into()),
223        };
224
225        visitor.visit_str(string)
226    }
227
228    fn get_byte_buffer(&mut self, length: usize) -> Result<Vec<u8>> {
229        self.fill_buffer(length)?;
230        Ok(core::mem::take(&mut self.temp_buffer))
231    }
232
233    fn forward_read_bytes<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
234    where
235        V: serde::de::Visitor<'a>,
236    {
237        self.fill_buffer(length)?;
238        visitor.visit_bytes(&self.temp_buffer[..])
239    }
240
241    #[inline(always)]
242    fn barrier(&self) -> usize {
243        self.barrier_offset
244    }
245
246    #[inline(always)]
247    fn set_barrier(&mut self, offset: usize) {
248        self.barrier_offset = offset;
249    }
250
251    #[inline(always)]
252    fn forward_to_barrier(&mut self) -> io::Result<()> {
253        let mut v = vec![0u8; self.barrier_offset];
254        self.barrier_offset = 0;
255        self.reader.read_exact(&mut v)?;
256        Ok(())
257    }
258}
259
260#[cfg(test)]
261mod test {
262    use super::IoReader;
263
264    #[test]
265    fn test_fill_buffer() {
266        let buffer = vec![0u8; 64];
267        let mut reader = IoReader::new(buffer.as_slice());
268
269        reader.fill_buffer(20).unwrap();
270        assert_eq!(20, reader.temp_buffer.len());
271
272        reader.fill_buffer(30).unwrap();
273        assert_eq!(30, reader.temp_buffer.len());
274
275        reader.fill_buffer(5).unwrap();
276        assert_eq!(5, reader.temp_buffer.len());
277    }
278}