Skip to main content

multi_cbor/
read.rs

1#[cfg(feature = "alloc")]
2use alloc::{vec, vec::Vec};
3#[cfg(feature = "std")]
4use core::cmp;
5
6#[cfg(feature = "std")]
7use std::io::{self, Read as StdRead};
8
9use crate::error::{Error, ErrorCode, Result};
10
11#[cfg(not(feature = "unsealed_read_write"))]
12/// Trait used by the deserializer for iterating over input.
13///
14/// This trait is sealed by default, enabling the `unsealed_read_write` feature removes this bound
15/// to allow objects outside of this crate to implement this trait.
16pub trait Read<'de>: private::Sealed {
17    #[doc(hidden)]
18    /// Read n bytes from the input.
19    ///
20    /// Implementations that can are asked to return a slice with a Long lifetime that outlives the
21    /// decoder, but others (eg. ones that need to allocate the data into a temporary buffer) can
22    /// return it with a Short lifetime that just lives for the time of read's mutable borrow of
23    /// the reader.
24    ///
25    /// This may, as a side effect, clear the reader's scratch buffer (as the provided
26    /// implementation does).
27    ///
28    /// A more appropriate lifetime setup for this (that would allow the Deserializer::convert_str
29    /// to stay a function) would be something like `fn read<'a, 'r: 'a>(&'a mut 'r immut self, ...) -> ...
30    /// EitherLifetime<'r, 'de>>`, which borrows self mutably for the duration of the function and
31    /// downgrates that reference to an immutable one that outlives the result (protecting the
32    /// scratch buffer from changes), but alas, that can't be expressed (yet?).
33    fn read<'a>(&'a mut self, n: usize) -> Result<EitherLifetime<'a, 'de>> {
34        self.clear_buffer();
35        self.read_to_buffer(n)?;
36
37        Ok(self.take_buffer())
38    }
39
40    #[doc(hidden)]
41    fn next(&mut self) -> Result<Option<u8>>;
42
43    #[doc(hidden)]
44    fn peek(&mut self) -> Result<Option<u8>>;
45
46    #[doc(hidden)]
47    fn clear_buffer(&mut self);
48
49    #[doc(hidden)]
50    fn read_to_buffer(&mut self, n: usize) -> Result<()>;
51
52    #[doc(hidden)]
53    fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de>;
54
55    #[doc(hidden)]
56    fn read_into(&mut self, buf: &mut [u8]) -> Result<()>;
57
58    #[doc(hidden)]
59    fn discard(&mut self);
60
61    #[doc(hidden)]
62    fn offset(&self) -> u64;
63}
64
65#[cfg(feature = "unsealed_read_write")]
66/// Trait used by the deserializer for iterating over input.
67pub trait Read<'de> {
68    /// Read n bytes from the input.
69    ///
70    /// Implementations that can are asked to return a slice with a Long lifetime that outlives the
71    /// decoder, but others (eg. ones that need to allocate the data into a temporary buffer) can
72    /// return it with a Short lifetime that just lives for the time of read's mutable borrow of
73    /// the reader.
74    ///
75    /// This may, as a side effect, clear the reader's scratch buffer (as the provided
76    /// implementation does).
77    ///
78    /// A more appropriate lifetime setup for this (that would allow the `Deserializer::convert_str`
79    /// to stay a function) would be something like `fn read<'a, 'r: 'a>(&'a mut 'r immut self, ...) -> ...
80    /// EitherLifetime<'r, 'de>>`, which borrows self mutably for the duration of the function and
81    /// downgrates that reference to an immutable one that outlives the result (protecting the
82    /// scratch buffer from changes), but alas, that can't be expressed (yet?).
83    fn read<'a>(&'a mut self, n: usize) -> Result<EitherLifetime<'a, 'de>> {
84        self.clear_buffer();
85        self.read_to_buffer(n)?;
86
87        Ok(self.take_buffer())
88    }
89
90    /// Read the next byte from the input, if any.
91    fn next(&mut self) -> Result<Option<u8>>;
92
93    /// Peek at the next byte of the input, if any. This does not advance the reader, so the result
94    /// of this function will remain the same until a read or clear occurs.
95    fn peek(&mut self) -> Result<Option<u8>>;
96
97    /// Clear the underlying scratch buffer
98    fn clear_buffer(&mut self);
99
100    /// Append n bytes from the reader to the reader's scratch buffer (without clearing it)
101    fn read_to_buffer(&mut self, n: usize) -> Result<()>;
102
103    /// Read out everything accumulated in the reader's scratch buffer. This may, as a side effect,
104    /// clear it.
105    fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de>;
106
107    /// Read from the input until `buf` is full or end of input is encountered.
108    fn read_into(&mut self, buf: &mut [u8]) -> Result<()>;
109
110    /// Discard any data read by `peek`.
111    fn discard(&mut self);
112
113    /// Returns the offset from the start of the reader.
114    fn offset(&self) -> u64;
115}
116
117/// Represents a reader that can return its current position
118pub trait Offset {
119    fn byte_offset(&self) -> usize;
120}
121
122/// Represents a buffer with one of two lifetimes.
123pub enum EitherLifetime<'short, 'long> {
124    /// The short lifetime
125    Short(&'short [u8]),
126    /// The long lifetime
127    Long(&'long [u8]),
128}
129
130#[cfg(not(feature = "unsealed_read_write"))]
131mod private {
132    pub trait Sealed {}
133}
134
135/// CBOR input source that reads from a `std::io` input stream.
136#[cfg(feature = "std")]
137#[derive(Debug)]
138pub struct IoRead<R>
139where
140    R: io::Read,
141{
142    reader: OffsetReader<R>,
143    scratch: Vec<u8>,
144    ch: Option<u8>,
145}
146
147#[cfg(feature = "std")]
148impl<R> IoRead<R>
149where
150    R: io::Read,
151{
152    /// Creates a new CBOR input source to read from a `std::io` input stream.
153    pub const fn new(reader: R) -> Self {
154        Self {
155            reader: OffsetReader { reader, offset: 0 },
156            scratch: vec![],
157            ch: None,
158        }
159    }
160
161    #[inline]
162    fn next_inner(&mut self) -> Result<Option<u8>> {
163        let mut buf = [0; 1];
164        loop {
165            match self.reader.read(&mut buf) {
166                Ok(0) => return Ok(None),
167                Ok(_) => return Ok(Some(buf[0])),
168                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
169                Err(e) => return Err(Error::io(e)),
170            }
171        }
172    }
173}
174
175#[cfg(all(feature = "std", not(feature = "unsealed_read_write")))]
176impl<R> private::Sealed for IoRead<R> where R: io::Read {}
177
178#[cfg(feature = "std")]
179impl<'de, R> Read<'de> for IoRead<R>
180where
181    R: io::Read,
182{
183    #[inline]
184    fn next(&mut self) -> Result<Option<u8>> {
185        match self.ch.take() {
186            Some(ch) => Ok(Some(ch)),
187            None => self.next_inner(),
188        }
189    }
190
191    #[inline]
192    fn peek(&mut self) -> Result<Option<u8>> {
193        if let Some(ch) = self.ch {
194            Ok(Some(ch))
195        } else {
196            self.ch = self.next_inner()?;
197            Ok(self.ch)
198        }
199    }
200
201    fn read_to_buffer(&mut self, mut n: usize) -> Result<()> {
202        // defend against malicious input pretending to be huge strings by limiting growth
203        self.scratch.reserve(cmp::min(n, 16 * 1024));
204
205        if n == 0 {
206            return Ok(());
207        }
208
209        if let Some(ch) = self.ch.take() {
210            self.scratch.push(ch);
211            n -= 1;
212        }
213
214        // n == 0 is OK here and needs no further special treatment
215
216        let transfer_result = {
217            // Prepare for take() (which consumes its reader) by creating a reference adaptor
218            // that'll only live in this block
219            let reference = self.reader.by_ref();
220            // Append the first n bytes of the reader to the scratch vector (or up to
221            // an error or EOF indicated by a shorter read)
222            let mut taken = reference.take(n as u64);
223            taken.read_to_end(&mut self.scratch)
224        };
225
226        match transfer_result {
227            Ok(r) if r == n => Ok(()),
228            Ok(_) => Err(Error::syntax(
229                ErrorCode::EofWhileParsingValue,
230                self.offset(),
231            )),
232            Err(e) => Err(Error::io(e)),
233        }
234    }
235
236    fn clear_buffer(&mut self) {
237        self.scratch.clear();
238    }
239
240    fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de> {
241        EitherLifetime::Short(&self.scratch)
242    }
243
244    fn read_into(&mut self, buf: &mut [u8]) -> Result<()> {
245        self.reader.read_exact(buf).map_err(|e| {
246            if e.kind() == io::ErrorKind::UnexpectedEof {
247                Error::syntax(ErrorCode::EofWhileParsingValue, self.offset())
248            } else {
249                Error::io(e)
250            }
251        })
252    }
253
254    #[inline]
255    fn discard(&mut self) {
256        self.ch = None;
257    }
258
259    fn offset(&self) -> u64 {
260        self.reader.offset
261    }
262}
263
264#[cfg(feature = "std")]
265impl<R> Offset for IoRead<R>
266where
267    R: std::io::Read,
268{
269    fn byte_offset(&self) -> usize {
270        self.offset() as usize
271    }
272}
273
274#[cfg(feature = "std")]
275#[derive(Debug)]
276struct OffsetReader<R> {
277    reader: R,
278    offset: u64,
279}
280
281#[cfg(feature = "std")]
282impl<R> io::Read for OffsetReader<R>
283where
284    R: io::Read,
285{
286    #[inline]
287    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
288        let r = self.reader.read(buf);
289        if let Ok(count) = r {
290            self.offset += count as u64;
291        }
292        r
293    }
294}
295
296/// A CBOR input source that reads from a slice of bytes.
297#[cfg(any(feature = "std", feature = "alloc"))]
298#[derive(Debug)]
299pub struct SliceRead<'a> {
300    slice: &'a [u8],
301    scratch: Vec<u8>,
302    index: usize,
303}
304
305#[cfg(any(feature = "std", feature = "alloc"))]
306impl<'a> SliceRead<'a> {
307    /// Creates a CBOR input source to read from a slice of bytes.
308    #[must_use]
309    pub const fn new(slice: &'a [u8]) -> Self {
310        SliceRead {
311            slice,
312            scratch: vec![],
313            index: 0,
314        }
315    }
316
317    fn end(&self, n: usize) -> Result<usize> {
318        match self.index.checked_add(n) {
319            Some(end) if end <= self.slice.len() => Ok(end),
320            _ => Err(Error::syntax(
321                ErrorCode::EofWhileParsingValue,
322                self.slice.len() as u64,
323            )),
324        }
325    }
326}
327
328#[cfg(any(feature = "std", feature = "alloc"))]
329impl Offset for SliceRead<'_> {
330    #[inline]
331    fn byte_offset(&self) -> usize {
332        self.index
333    }
334}
335
336#[cfg(all(
337    any(feature = "std", feature = "alloc"),
338    not(feature = "unsealed_read_write")
339))]
340impl private::Sealed for SliceRead<'_> {}
341
342#[cfg(any(feature = "std", feature = "alloc"))]
343impl<'a> Read<'a> for SliceRead<'a> {
344    #[inline]
345    fn next(&mut self) -> Result<Option<u8>> {
346        Ok(if self.index < self.slice.len() {
347            let ch = self.slice[self.index];
348            self.index += 1;
349            Some(ch)
350        } else {
351            None
352        })
353    }
354
355    #[inline]
356    fn peek(&mut self) -> Result<Option<u8>> {
357        Ok(if self.index < self.slice.len() {
358            Some(self.slice[self.index])
359        } else {
360            None
361        })
362    }
363
364    fn clear_buffer(&mut self) {
365        self.scratch.clear();
366    }
367
368    fn read_to_buffer(&mut self, n: usize) -> Result<()> {
369        let end = self.end(n)?;
370        let slice = &self.slice[self.index..end];
371        self.scratch.extend_from_slice(slice);
372        self.index = end;
373
374        Ok(())
375    }
376
377    #[inline]
378    fn read<'b>(&'b mut self, n: usize) -> Result<EitherLifetime<'b, 'a>> {
379        let end = self.end(n)?;
380        let slice = &self.slice[self.index..end];
381        self.index = end;
382        Ok(EitherLifetime::Long(slice))
383    }
384
385    fn take_buffer<'b>(&'b mut self) -> EitherLifetime<'b, 'a> {
386        EitherLifetime::Short(&self.scratch)
387    }
388
389    #[inline]
390    fn read_into(&mut self, buf: &mut [u8]) -> Result<()> {
391        let end = self.end(buf.len())?;
392        buf.copy_from_slice(&self.slice[self.index..end]);
393        self.index = end;
394        Ok(())
395    }
396
397    #[inline]
398    fn discard(&mut self) {
399        self.index += 1;
400    }
401
402    fn offset(&self) -> u64 {
403        self.index as u64
404    }
405}
406
407/// A CBOR input source that reads from a slice of bytes using a fixed size scratch buffer.
408///
409/// [`SliceRead`](struct.SliceRead.html) and [`MutSliceRead`](struct.MutSliceRead.html) are usually
410/// preferred over this, as they can handle indefinite length items.
411#[derive(Debug)]
412pub struct SliceReadFixed<'a, 'b> {
413    slice: &'a [u8],
414    scratch: &'b mut [u8],
415    index: usize,
416    scratch_index: usize,
417}
418
419impl<'a, 'b> SliceReadFixed<'a, 'b> {
420    /// Creates a CBOR input source to read from a slice of bytes, backed by a scratch buffer.
421    pub const fn new(slice: &'a [u8], scratch: &'b mut [u8]) -> Self {
422        SliceReadFixed {
423            slice,
424            scratch,
425            index: 0,
426            scratch_index: 0,
427        }
428    }
429
430    fn end(&self, n: usize) -> Result<usize> {
431        match self.index.checked_add(n) {
432            Some(end) if end <= self.slice.len() => Ok(end),
433            _ => Err(Error::syntax(
434                ErrorCode::EofWhileParsingValue,
435                self.slice.len() as u64,
436            )),
437        }
438    }
439
440    fn scratch_end(&self, n: usize) -> Result<usize> {
441        match self.scratch_index.checked_add(n) {
442            Some(end) if end <= self.scratch.len() => Ok(end),
443            _ => Err(Error::scratch_too_small(self.index as u64)),
444        }
445    }
446}
447
448#[cfg(not(feature = "unsealed_read_write"))]
449impl private::Sealed for SliceReadFixed<'_, '_> {}
450
451impl<'a> Read<'a> for SliceReadFixed<'a, '_> {
452    #[inline]
453    fn next(&mut self) -> Result<Option<u8>> {
454        Ok(if self.index < self.slice.len() {
455            let ch = self.slice[self.index];
456            self.index += 1;
457            Some(ch)
458        } else {
459            None
460        })
461    }
462
463    #[inline]
464    fn peek(&mut self) -> Result<Option<u8>> {
465        Ok(if self.index < self.slice.len() {
466            Some(self.slice[self.index])
467        } else {
468            None
469        })
470    }
471
472    fn clear_buffer(&mut self) {
473        self.scratch_index = 0;
474    }
475
476    fn read_to_buffer(&mut self, n: usize) -> Result<()> {
477        let end = self.end(n)?;
478        let scratch_end = self.scratch_end(n)?;
479        let slice = &self.slice[self.index..end];
480        self.scratch[self.scratch_index..scratch_end].copy_from_slice(slice);
481        self.index = end;
482        self.scratch_index = scratch_end;
483
484        Ok(())
485    }
486
487    fn read<'c>(&'c mut self, n: usize) -> Result<EitherLifetime<'c, 'a>> {
488        let end = self.end(n)?;
489        let slice = &self.slice[self.index..end];
490        self.index = end;
491        Ok(EitherLifetime::Long(slice))
492    }
493
494    fn take_buffer<'c>(&'c mut self) -> EitherLifetime<'c, 'a> {
495        EitherLifetime::Short(&self.scratch[0..self.scratch_index])
496    }
497
498    #[inline]
499    fn read_into(&mut self, buf: &mut [u8]) -> Result<()> {
500        let end = self.end(buf.len())?;
501        buf.copy_from_slice(&self.slice[self.index..end]);
502        self.index = end;
503        Ok(())
504    }
505
506    #[inline]
507    fn discard(&mut self) {
508        self.index += 1;
509    }
510
511    fn offset(&self) -> u64 {
512        self.index as u64
513    }
514}
515
516#[cfg(any(feature = "std", feature = "alloc"))]
517impl Offset for SliceReadFixed<'_, '_> {
518    #[inline]
519    fn byte_offset(&self) -> usize {
520        self.index
521    }
522}
523
524/// A CBOR input source that reads from a slice of bytes, and can move data around internally to
525/// reassemble indefinite strings without the need of an allocated scratch buffer.
526#[derive(Debug)]
527pub struct MutSliceRead<'a> {
528    /// A complete view of the reader's data. It is promised that bytes before `buffer_end` are not
529    /// mutated any more.
530    slice: &'a mut [u8],
531    /// Read cursor position in slice
532    index: usize,
533    /// Number of bytes already discarded from the slice
534    before: usize,
535    /// End of the buffer area that contains all bytes `read_into_buffer`. This is always <= index.
536    buffer_end: usize,
537}
538
539impl<'a> MutSliceRead<'a> {
540    /// Creates a CBOR input source to read from a slice of bytes.
541    pub const fn new(slice: &'a mut [u8]) -> Self {
542        MutSliceRead {
543            slice,
544            index: 0,
545            before: 0,
546            buffer_end: 0,
547        }
548    }
549
550    fn end(&self, n: usize) -> Result<usize> {
551        match self.index.checked_add(n) {
552            Some(end) if end <= self.slice.len() => Ok(end),
553            _ => Err(Error::syntax(
554                ErrorCode::EofWhileParsingValue,
555                self.slice.len() as u64,
556            )),
557        }
558    }
559}
560
561#[cfg(not(feature = "unsealed_read_write"))]
562impl private::Sealed for MutSliceRead<'_> {}
563
564impl<'a> Read<'a> for MutSliceRead<'a> {
565    #[inline]
566    fn next(&mut self) -> Result<Option<u8>> {
567        // This is duplicated from SliceRead, can that be eased?
568        Ok(if self.index < self.slice.len() {
569            let ch = self.slice[self.index];
570            self.index += 1;
571            Some(ch)
572        } else {
573            None
574        })
575    }
576
577    #[inline]
578    fn peek(&mut self) -> Result<Option<u8>> {
579        // This is duplicated from SliceRead, can that be eased?
580        Ok(if self.index < self.slice.len() {
581            Some(self.slice[self.index])
582        } else {
583            None
584        })
585    }
586
587    fn clear_buffer(&mut self) {
588        self.slice = &mut core::mem::take(&mut self.slice)[self.index..];
589        self.before += self.index;
590        self.index = 0;
591        self.buffer_end = 0;
592    }
593
594    fn read_to_buffer(&mut self, n: usize) -> Result<()> {
595        let end = self.end(n)?;
596        debug_assert!(
597            self.buffer_end <= self.index,
598            "MutSliceRead invariant violated: scratch buffer exceeds index"
599        );
600        self.slice[self.buffer_end..end].rotate_left(self.index - self.buffer_end);
601        self.buffer_end += n;
602        self.index = end;
603
604        Ok(())
605    }
606
607    fn take_buffer<'b>(&'b mut self) -> EitherLifetime<'b, 'a> {
608        let (left, right) = core::mem::take(&mut self.slice).split_at_mut(self.index);
609        self.slice = right;
610        self.before += self.index;
611        self.index = 0;
612
613        let left = &left[..self.buffer_end];
614        self.buffer_end = 0;
615
616        EitherLifetime::Long(left)
617    }
618
619    #[inline]
620    fn read_into(&mut self, buf: &mut [u8]) -> Result<()> {
621        // This is duplicated from SliceRead, can that be eased?
622        let end = self.end(buf.len())?;
623        buf.copy_from_slice(&self.slice[self.index..end]);
624        self.index = end;
625        Ok(())
626    }
627
628    #[inline]
629    fn discard(&mut self) {
630        self.index += 1;
631    }
632
633    fn offset(&self) -> u64 {
634        (self.before + self.index) as u64
635    }
636}