#[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};
usecrate::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. pubtrait 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 mutself, n: usize) -> Result<EitherLifetime<'a, 'de>> { self.clear_buffer(); self.read_to_buffer(n)?;
#[cfg(feature = "unsealed_read_write")] /// Trait used by the deserializer for iterating over input. pubtrait 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 mutself, n: usize) -> Result<EitherLifetime<'a, 'de>> { self.clear_buffer(); self.read_to_buffer(n)?;
Ok(self.take_buffer())
}
/// Read the next byte from the input, if any. fn next(&mutself) -> Result<Option<u8>>;
/// 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(&mutself) -> Result<Option<u8>>;
/// Clear the underlying scratch buffer fn clear_buffer(&mutself);
/// Append n bytes from the reader to the reader's scratch buffer (without clearing it) fn read_to_buffer(&mutself, 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 mutself) -> EitherLifetime<'a, 'de>;
/// Read from the input until `buf` is full or end of input is encountered. fn read_into(&mutself, buf: &mut [u8]) -> Result<()>;
/// Discard any data read by `peek`. fn discard(&mutself);
/// Returns the offset from the start of the reader. fn offset(&self) -> u64;
}
/// Represents a reader that can return its current position pubtrait Offset { fn byte_offset(&self) -> usize;
}
/// Represents a buffer with one of two lifetimes. pubenum EitherLifetime<'short, 'long> { /// The short lifetime
Short(&'short [u8]), /// The long lifetime
Long(&'long [u8]),
}
#[cfg(not(feature = "unsealed_read_write"))] mod private { pubtrait Sealed {}
}
/// CBOR input source that reads from a std::io input stream. #[cfg(feature = "std")] #[derive(Debug)] pubstruct IoRead<R> where
R: io::Read,
{
reader: OffsetReader<R>,
scratch: Vec<u8>,
ch: Option<u8>,
}
#[cfg(feature = "std")] impl<R> IoRead<R> where
R: io::Read,
{ /// Creates a new CBOR input source to read from a std::io input stream. pubfn new(reader: R) -> IoRead<R> {
IoRead {
reader: OffsetReader { reader, offset: 0 },
scratch: vec![],
ch: None,
}
}
fn read_to_buffer(&mutself, 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(());
}
iflet 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) letmut taken = reference.take(n as u64);
taken.read_to_end(&mutself.scratch)
};
match transfer_result {
Ok(r) if r == n => Ok(()),
Ok(_) => Err(Error::syntax(
ErrorCode::EofWhileParsingValue, self.offset(),
)),
Err(e) => Err(Error::io(e)),
}
}
/// 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)] pubstruct 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. pubfn 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<usize> { matchself.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<usize> { matchself.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> {}
/// 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)] pubstruct 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. pubfn new(slice: &'a mut [u8]) -> MutSliceRead<'a> {
MutSliceRead {
slice,
index: 0,
before: 0,
buffer_end: 0,
}
}
fn end(&self, n: usize) -> Result<usize> { matchself.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(&mutself) -> Result<Option<u8>> { // This is duplicated from SliceRead, can that be eased?
Ok(ifself.index < self.slice.len() { let ch = self.slice[self.index]; self.index += 1;
Some(ch)
} else {
None
})
}
#[inline] fn peek(&mutself) -> Result<Option<u8>> { // This is duplicated from SliceRead, can that be eased?
Ok(ifself.index < self.slice.len() {
Some(self.slice[self.index])
} else {
None
})
}
let left = &left[..self.buffer_end]; self.buffer_end = 0;
EitherLifetime::Long(left)
}
#[inline] fn read_into(&mutself, 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(())
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.