Skip to main content

minicbor_io/
reader.rs

1use crate::Error;
2use minicbor::Decode;
3use std::io;
4
5/// Wraps a [`std::io::Read`] and reads length-delimited CBOR values.
6#[derive(Debug)]
7pub struct Reader<R> {
8    reader: R,
9    buffer: Vec<u8>,
10    max_len: usize
11}
12
13impl<R> Reader<R> {
14    /// Create a new reader with a max. buffer size of 512KiB.
15    pub fn new(reader: R) -> Self {
16        Self::with_buffer(reader, Vec::new())
17    }
18
19    /// Create a new reader with a max. buffer size of 512KiB.
20    pub fn with_buffer(reader: R, buffer: Vec<u8>) -> Self {
21        Self { reader, buffer, max_len: 512 * 1024 }
22    }
23
24    /// Set the max. buffer size in bytes.
25    ///
26    /// If length values greater than this are decoded, an
27    /// [`Error::InvalidLen`] will be returned.
28    pub fn set_max_len(&mut self, val: u32) {
29        self.max_len = val as usize
30    }
31
32    /// Get a reference to the inner buffer.
33    pub fn buffer(&self) -> &Vec<u8> {
34        &self.buffer
35    }
36
37    /// Get a mutable reference to the inner buffer.
38    pub fn buffer_mut(&mut self) -> &mut Vec<u8> {
39        &mut self.buffer
40    }
41
42    /// Get a reference to the inner reader.
43    pub fn reader(&self) -> &R {
44        &self.reader
45    }
46
47    /// Get a mutable reference to the inner reader.
48    pub fn reader_mut(&mut self) -> &mut R {
49        &mut self.reader
50    }
51
52    /// Deconstruct this reader into the inner reader and the buffer.
53    pub fn into_parts(self) -> (R, Vec<u8>) {
54        (self.reader, self.buffer)
55    }
56}
57
58impl<R: io::Read> Reader<R> {
59    /// Read the next CBOR value and decode it.
60    ///
61    /// The value is assumed to be preceded by a `u32` (4 bytes in network
62    /// byte order) denoting the length of the CBOR item in bytes.
63    ///
64    /// Reading 0 bytes when decoding the length prefix results in `Ok(None)`,
65    /// otherwise either `Some` value or an error is returned.
66    pub fn read<'a, T: Decode<'a, ()>>(&'a mut self) -> Result<Option<T>, Error> {
67        self.read_with(&mut ())
68    }
69
70    /// Like [`Reader::read`] but accepting a user provided decoding context.
71    pub fn read_with<'a, C, T: Decode<'a, C>>(&'a mut self, ctx: &mut C) -> Result<Option<T>, Error> {
72        let mut buf = [0; 4];
73        let mut len = 0;
74        while len < 4 {
75            match self.reader.read(&mut buf[len ..]) {
76                Ok(0) if len == 0 =>
77                    return Ok(None),
78                Ok(0) =>
79                    return Err(Error::Io(io::ErrorKind::UnexpectedEof.into())),
80                Ok(n) =>
81                    len += n,
82                Err(e) if e.kind() == io::ErrorKind::Interrupted =>
83                    continue,
84                Err(e) =>
85                    return Err(Error::Io(e))
86            }
87        }
88        let len = u32::from_be_bytes(buf) as usize;
89        if len > self.max_len {
90            return Err(Error::InvalidLen)
91        }
92        self.buffer.clear();
93        self.buffer.resize(len, 0u8);
94        self.reader.read_exact(&mut self.buffer)?;
95        minicbor::decode_with(&self.buffer, ctx).map_err(Error::Decode).map(Some)
96    }
97}
98