Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  read.rs   Sprache: unbekannt

 
#[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<EitherLifetime<'a, 'de>> {
        self.clear_buffer();
        self.read_to_buffer(n)?;

        Ok(self.take_buffer())
    }

    #[doc(hidden)]
    fn next(&mut self) -> Result<Option<u8>>;

    #[doc(hidden)]
    fn peek(&mut self) -> Result<Option<u8>>;

    #[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<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(&mut self) -> 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(&mut self) -> Result<Option<u8>>;

    /// 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<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.
    pub fn new(reader: R) -> IoRead<R> {
        IoRead {
            reader: OffsetReader { reader, offset: 0 },
            scratch: vec![],
            ch: None,
        }
    }

    #[inline]
    fn next_inner(&mut self) -> Result<Option<u8>> {
        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<R> private::Sealed for IoRead<R> where R: io::Read {}

#[cfg(feature = "std")]
impl<'de, R> Read<'de> for IoRead<R>
where
    R: io::Read,
{
    #[inline]
    fn next(&mut self) -> Result<Option<u8>> {
        match self.ch.take() {
            Some(ch) => Ok(Some(ch)),
            None => self.next_inner(),
        }
    }

    #[inline]
    fn peek(&mut self) -> Result<Option<u8>> {
        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<R> Offset for IoRead<R>
where
    R: std::io::Read,
{
    fn byte_offset(&self) -> usize {
        self.offset() as usize
    }
}

#[cfg(feature = "std")]
#[derive(Debug)]
struct OffsetReader<R> {
    reader: R,
    offset: u64,
}

#[cfg(feature = "std")]
impl<R> io::Read for OffsetReader<R>
where
    R: io::Read,
{
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        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<u8>,
    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<usize> {
        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<Option<u8>> {
        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<Option<u8>> {
        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<EitherLifetime<'b, 'a>> {
        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<usize> {
        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<usize> {
        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<Option<u8>> {
        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<Option<u8>> {
        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<EitherLifetime<'c, 'a>> {
        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<usize> {
        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<Option<u8>> {
        // 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<Option<u8>> {
        // 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
    }
}

[ Dauer der Verarbeitung: 0.25 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge