#[cfg(feature = "alloc")] use alloc::{vec, vec::Vec}; #[cfg(feature = "std")] use core::cmp; use core::mem; #[cfg(feature = "std")] use std::io::{self, Read as StdRead}; use crate::error::{Error, ErrorCode, Result}; #[cfg(not(feature = "unsealed_read_write"))] /// Trait used by the deserializer for iterating over input. /// /// This trait is sealed by default, enabling the `unsealed_read_write` feature removes this bound /// to allow objects outside of this crate to implement this trait. pub trait Read<'de>: private::Sealed { #[doc(hidden)] /// Read n bytes from the input. /// /// Implementations that can are asked to return a slice with a Long lifetime that outlives the /// decoder, but others (eg. ones that need to allocate the data into a temporary buffer) can /// return it with a Short lifetime that just lives for the time of read's mutable borrow of /// the reader. /// /// This may, as a side effect, clear the reader's scratch buffer (as the provided /// implementation does). // A more appropriate lifetime setup for this (that would allow the Deserializer::convert_str // to stay a function) would be something like `fn read<'a, 'r: 'a>(&'a mut 'r immut self, ...) -> ... // EitherLifetime<'r, 'de>>`, which borrows self mutably for the duration of the function and // downgrates that reference to an immutable one that outlives the result (protecting the // scratch buffer from changes), but alas, that can't be expressed (yet?). fn read<'a>(&'a mut self, n: usize) -> Result> { self.clear_buffer(); self.read_to_buffer(n)?; Ok(self.take_buffer()) } #[doc(hidden)] fn next(&mut self) -> Result>; #[doc(hidden)] fn peek(&mut self) -> Result>; #[doc(hidden)] fn clear_buffer(&mut self); #[doc(hidden)] fn read_to_buffer(&mut self, n: usize) -> Result<()>; #[doc(hidden)] fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de>; #[doc(hidden)] fn read_into(&mut self, buf: &mut [u8]) -> Result<()>; #[doc(hidden)] fn discard(&mut self); #[doc(hidden)] fn offset(&self) -> u64; } #[cfg(feature = "unsealed_read_write")] /// Trait used by the deserializer for iterating over input. pub trait Read<'de> { /// Read n bytes from the input. /// /// Implementations that can are asked to return a slice with a Long lifetime that outlives the /// decoder, but others (eg. ones that need to allocate the data into a temporary buffer) can /// return it with a Short lifetime that just lives for the time of read's mutable borrow of /// the reader. /// /// This may, as a side effect, clear the reader's scratch buffer (as the provided /// implementation does). // A more appropriate lifetime setup for this (that would allow the Deserializer::convert_str // to stay a function) would be something like `fn read<'a, 'r: 'a>(&'a mut 'r immut self, ...) -> ... // EitherLifetime<'r, 'de>>`, which borrows self mutably for the duration of the function and // downgrates that reference to an immutable one that outlives the result (protecting the // scratch buffer from changes), but alas, that can't be expressed (yet?). fn read<'a>(&'a mut self, n: usize) -> Result> { self.clear_buffer(); self.read_to_buffer(n)?; Ok(self.take_buffer()) } /// Read the next byte from the input, if any. fn next(&mut self) -> Result>; /// Peek at the next byte of the input, if any. This does not advance the reader, so the result /// of this function will remain the same until a read or clear occurs. fn peek(&mut self) -> Result>; /// Clear the underlying scratch buffer fn clear_buffer(&mut self); /// Append n bytes from the reader to the reader's scratch buffer (without clearing it) fn read_to_buffer(&mut self, n: usize) -> Result<()>; /// Read out everything accumulated in the reader's scratch buffer. This may, as a side effect, /// clear it. fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de>; /// Read from the input until `buf` is full or end of input is encountered. fn read_into(&mut self, buf: &mut [u8]) -> Result<()>; /// Discard any data read by `peek`. fn discard(&mut self); /// Returns the offset from the start of the reader. fn offset(&self) -> u64; } /// Represents a reader that can return its current position pub trait Offset { fn byte_offset(&self) -> usize; } /// Represents a buffer with one of two lifetimes. pub enum EitherLifetime<'short, 'long> { /// The short lifetime Short(&'short [u8]), /// The long lifetime Long(&'long [u8]), } #[cfg(not(feature = "unsealed_read_write"))] mod private { pub trait Sealed {} } /// CBOR input source that reads from a std::io input stream. #[cfg(feature = "std")] #[derive(Debug)] pub struct IoRead where R: io::Read, { reader: OffsetReader, scratch: Vec, ch: Option, } #[cfg(feature = "std")] impl IoRead where R: io::Read, { /// Creates a new CBOR input source to read from a std::io input stream. pub fn new(reader: R) -> IoRead { IoRead { reader: OffsetReader { reader, offset: 0 }, scratch: vec![], ch: None, } } #[inline] fn next_inner(&mut self) -> Result> { let mut buf = [0; 1]; loop { match self.reader.read(&mut buf) { Ok(0) => return Ok(None), Ok(_) => return Ok(Some(buf[0])), Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} Err(e) => return Err(Error::io(e)), } } } } #[cfg(all(feature = "std", not(feature = "unsealed_read_write")))] impl private::Sealed for IoRead where R: io::Read {} #[cfg(feature = "std")] impl<'de, R> Read<'de> for IoRead where R: io::Read, { #[inline] fn next(&mut self) -> Result> { match self.ch.take() { Some(ch) => Ok(Some(ch)), None => self.next_inner(), } } #[inline] fn peek(&mut self) -> Result> { match self.ch { Some(ch) => Ok(Some(ch)), None => { self.ch = self.next_inner()?; Ok(self.ch) } } } fn read_to_buffer(&mut self, mut n: usize) -> Result<()> { // defend against malicious input pretending to be huge strings by limiting growth self.scratch.reserve(cmp::min(n, 16 * 1024)); if n == 0 { return Ok(()); } if let Some(ch) = self.ch.take() { self.scratch.push(ch); n -= 1; } // n == 0 is OK here and needs no further special treatment let transfer_result = { // Prepare for take() (which consumes its reader) by creating a reference adaptor // that'll only live in this block let reference = self.reader.by_ref(); // Append the first n bytes of the reader to the scratch vector (or up to // an error or EOF indicated by a shorter read) let mut taken = reference.take(n as u64); taken.read_to_end(&mut self.scratch) }; match transfer_result { Ok(r) if r == n => Ok(()), Ok(_) => Err(Error::syntax( ErrorCode::EofWhileParsingValue, self.offset(), )), Err(e) => Err(Error::io(e)), } } fn clear_buffer(&mut self) { self.scratch.clear(); } fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de> { EitherLifetime::Short(&self.scratch) } fn read_into(&mut self, buf: &mut [u8]) -> Result<()> { self.reader.read_exact(buf).map_err(|e| { if e.kind() == io::ErrorKind::UnexpectedEof { Error::syntax(ErrorCode::EofWhileParsingValue, self.offset()) } else { Error::io(e) } }) } #[inline] fn discard(&mut self) { self.ch = None; } fn offset(&self) -> u64 { self.reader.offset } } #[cfg(feature = "std")] impl Offset for IoRead where R: std::io::Read, { fn byte_offset(&self) -> usize { self.offset() as usize } } #[cfg(feature = "std")] #[derive(Debug)] struct OffsetReader { reader: R, offset: u64, } #[cfg(feature = "std")] impl io::Read for OffsetReader where R: io::Read, { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { let r = self.reader.read(buf); if let Ok(count) = r { self.offset += count as u64; } r } } /// A CBOR input source that reads from a slice of bytes. #[cfg(any(feature = "std", feature = "alloc"))] #[derive(Debug)] pub struct SliceRead<'a> { slice: &'a [u8], scratch: Vec, index: usize, } #[cfg(any(feature = "std", feature = "alloc"))] impl<'a> SliceRead<'a> { /// Creates a CBOR input source to read from a slice of bytes. pub fn new(slice: &'a [u8]) -> SliceRead<'a> { SliceRead { slice, scratch: vec![], index: 0, } } fn end(&self, n: usize) -> Result { match self.index.checked_add(n) { Some(end) if end <= self.slice.len() => Ok(end), _ => Err(Error::syntax( ErrorCode::EofWhileParsingValue, self.slice.len() as u64, )), } } } #[cfg(any(feature = "std", feature = "alloc"))] impl<'a> Offset for SliceRead<'a> { #[inline] fn byte_offset(&self) -> usize { self.index } } #[cfg(all( any(feature = "std", feature = "alloc"), not(feature = "unsealed_read_write") ))] impl<'a> private::Sealed for SliceRead<'a> {} #[cfg(any(feature = "std", feature = "alloc"))] impl<'a> Read<'a> for SliceRead<'a> { #[inline] fn next(&mut self) -> Result> { Ok(if self.index < self.slice.len() { let ch = self.slice[self.index]; self.index += 1; Some(ch) } else { None }) } #[inline] fn peek(&mut self) -> Result> { Ok(if self.index < self.slice.len() { Some(self.slice[self.index]) } else { None }) } fn clear_buffer(&mut self) { self.scratch.clear(); } fn read_to_buffer(&mut self, n: usize) -> Result<()> { let end = self.end(n)?; let slice = &self.slice[self.index..end]; self.scratch.extend_from_slice(slice); self.index = end; Ok(()) } #[inline] fn read<'b>(&'b mut self, n: usize) -> Result> { let end = self.end(n)?; let slice = &self.slice[self.index..end]; self.index = end; Ok(EitherLifetime::Long(slice)) } fn take_buffer<'b>(&'b mut self) -> EitherLifetime<'b, 'a> { EitherLifetime::Short(&self.scratch) } #[inline] fn read_into(&mut self, buf: &mut [u8]) -> Result<()> { let end = self.end(buf.len())?; buf.copy_from_slice(&self.slice[self.index..end]); self.index = end; Ok(()) } #[inline] fn discard(&mut self) { self.index += 1; } fn offset(&self) -> u64 { self.index as u64 } } /// A CBOR input source that reads from a slice of bytes using a fixed size scratch buffer. /// /// [`SliceRead`](struct.SliceRead.html) and [`MutSliceRead`](struct.MutSliceRead.html) are usually /// preferred over this, as they can handle indefinite length items. #[derive(Debug)] pub struct SliceReadFixed<'a, 'b> { slice: &'a [u8], scratch: &'b mut [u8], index: usize, scratch_index: usize, } impl<'a, 'b> SliceReadFixed<'a, 'b> { /// Creates a CBOR input source to read from a slice of bytes, backed by a scratch buffer. pub fn new(slice: &'a [u8], scratch: &'b mut [u8]) -> SliceReadFixed<'a, 'b> { SliceReadFixed { slice, scratch, index: 0, scratch_index: 0, } } fn end(&self, n: usize) -> Result { match self.index.checked_add(n) { Some(end) if end <= self.slice.len() => Ok(end), _ => Err(Error::syntax( ErrorCode::EofWhileParsingValue, self.slice.len() as u64, )), } } fn scratch_end(&self, n: usize) -> Result { match self.scratch_index.checked_add(n) { Some(end) if end <= self.scratch.len() => Ok(end), _ => Err(Error::scratch_too_small(self.index as u64)), } } } #[cfg(not(feature = "unsealed_read_write"))] impl<'a, 'b> private::Sealed for SliceReadFixed<'a, 'b> {} impl<'a, 'b> Read<'a> for SliceReadFixed<'a, 'b> { #[inline] fn next(&mut self) -> Result> { Ok(if self.index < self.slice.len() { let ch = self.slice[self.index]; self.index += 1; Some(ch) } else { None }) } #[inline] fn peek(&mut self) -> Result> { Ok(if self.index < self.slice.len() { Some(self.slice[self.index]) } else { None }) } fn clear_buffer(&mut self) { self.scratch_index = 0; } fn read_to_buffer(&mut self, n: usize) -> Result<()> { let end = self.end(n)?; let scratch_end = self.scratch_end(n)?; let slice = &self.slice[self.index..end]; self.scratch[self.scratch_index..scratch_end].copy_from_slice(&slice); self.index = end; self.scratch_index = scratch_end; Ok(()) } fn read<'c>(&'c mut self, n: usize) -> Result> { let end = self.end(n)?; let slice = &self.slice[self.index..end]; self.index = end; Ok(EitherLifetime::Long(slice)) } fn take_buffer<'c>(&'c mut self) -> EitherLifetime<'c, 'a> { EitherLifetime::Short(&self.scratch[0..self.scratch_index]) } #[inline] fn read_into(&mut self, buf: &mut [u8]) -> Result<()> { let end = self.end(buf.len())?; buf.copy_from_slice(&self.slice[self.index..end]); self.index = end; Ok(()) } #[inline] fn discard(&mut self) { self.index += 1; } fn offset(&self) -> u64 { self.index as u64 } } #[cfg(any(feature = "std", feature = "alloc"))] impl<'a, 'b> Offset for SliceReadFixed<'a, 'b> { #[inline] fn byte_offset(&self) -> usize { self.index } } /// A CBOR input source that reads from a slice of bytes, and can move data around internally to /// reassemble indefinite strings without the need of an allocated scratch buffer. #[derive(Debug)] pub struct MutSliceRead<'a> { /// A complete view of the reader's data. It is promised that bytes before buffer_end are not /// mutated any more. slice: &'a mut [u8], /// Read cursor position in slice index: usize, /// Number of bytes already discarded from the slice before: usize, /// End of the buffer area that contains all bytes read_into_buffer. This is always <= index. buffer_end: usize, } impl<'a> MutSliceRead<'a> { /// Creates a CBOR input source to read from a slice of bytes. pub fn new(slice: &'a mut [u8]) -> MutSliceRead<'a> { MutSliceRead { slice, index: 0, before: 0, buffer_end: 0, } } fn end(&self, n: usize) -> Result { match self.index.checked_add(n) { Some(end) if end <= self.slice.len() => Ok(end), _ => Err(Error::syntax( ErrorCode::EofWhileParsingValue, self.slice.len() as u64, )), } } } #[cfg(not(feature = "unsealed_read_write"))] impl<'a> private::Sealed for MutSliceRead<'a> {} impl<'a> Read<'a> for MutSliceRead<'a> { #[inline] fn next(&mut self) -> Result> { // This is duplicated from SliceRead, can that be eased? Ok(if self.index < self.slice.len() { let ch = self.slice[self.index]; self.index += 1; Some(ch) } else { None }) } #[inline] fn peek(&mut self) -> Result> { // This is duplicated from SliceRead, can that be eased? Ok(if self.index < self.slice.len() { Some(self.slice[self.index]) } else { None }) } fn clear_buffer(&mut self) { self.slice = &mut mem::replace(&mut self.slice, &mut [])[self.index..]; self.before += self.index; self.index = 0; self.buffer_end = 0; } fn read_to_buffer(&mut self, n: usize) -> Result<()> { let end = self.end(n)?; debug_assert!( self.buffer_end <= self.index, "MutSliceRead invariant violated: scratch buffer exceeds index" ); self.slice[self.buffer_end..end].rotate_left(self.index - self.buffer_end); self.buffer_end += n; self.index = end; Ok(()) } fn take_buffer<'b>(&'b mut self) -> EitherLifetime<'b, 'a> { let (left, right) = mem::replace(&mut self.slice, &mut []).split_at_mut(self.index); self.slice = right; self.before += self.index; self.index = 0; let left = &left[..self.buffer_end]; self.buffer_end = 0; EitherLifetime::Long(left) } #[inline] fn read_into(&mut self, buf: &mut [u8]) -> Result<()> { // This is duplicated from SliceRead, can that be eased? let end = self.end(buf.len())?; buf.copy_from_slice(&self.slice[self.index..end]); self.index = end; Ok(()) } #[inline] fn discard(&mut self) { self.index += 1; } fn offset(&self) -> u64 { (self.before + self.index) as u64 } }