preserves 5.0.0-rc.9

Implementation of the Preserves serialization format.
Documentation
use crate::error::SyntaxError;
use crate::reader::ReaderResult;

use std::borrow::Cow;
use std::io;

pub trait BinarySource<'de> {
    fn mark(&mut self) -> io::Result<usize>;
    fn restore(&mut self, mark: usize) -> io::Result<()>;
    fn input_position(&mut self) -> Option<usize>;

    fn skip(&mut self) -> io::Result<()>;
    fn peek(&mut self) -> io::Result<Option<u8>>;
    fn discard(&mut self, count: u64) -> ReaderResult<()>;
    fn readbytes(&mut self, count: u64) -> ReaderResult<Cow<'de, [u8]>>;
    fn readbytes_into(&mut self, bs: &mut [u8]) -> ReaderResult<()>;
    fn read_to_end(&mut self) -> ReaderResult<Cow<'de, [u8]>>;

    //---------------------------------------------------------------------------

    #[inline(always)]
    fn peek_noeof(&mut self) -> ReaderResult<u8> {
        self.peek()?.ok_or_else(|| self.wrap_syntax_error(SyntaxError::eof()))
    }

    #[inline(always)]
    fn read(&mut self) -> ReaderResult<u8> {
        let v = self.peek_noeof()?;
        self.skip()?;
        Ok(v)
    }

    fn wrap_syntax_error(&mut self, e: SyntaxError) -> crate::Error {
        e.at(self.input_position())
    }

    fn packed(&mut self) -> super::PackedReader<'de, &mut Self> where Self: Sized {
        super::PackedReader::new(self)
    }

    fn text(&mut self) -> super::TextReader<'de, &mut Self> where Self: Sized {
        super::TextReader::new(self)
    }

    fn into_packed(self) -> super::PackedReader<'de, Self> where Self: Sized {
        super::PackedReader::new(self)
    }

    fn into_text(self) -> super::TextReader<'de, Self> where Self: Sized {
        super::TextReader::new(self)
    }
}

impl<'de, 'a, T: BinarySource<'de> + ?Sized> BinarySource<'de> for &'a mut T {
    fn mark(&mut self) -> io::Result<usize> { (*self).mark() }
    fn restore(&mut self, mark: usize) -> io::Result<()> { (*self).restore(mark) }
    fn input_position(&mut self) -> Option<usize> { (*self).input_position() }
    fn skip(&mut self) -> io::Result<()> { (*self).skip() }
    fn peek(&mut self) -> io::Result<Option<u8>> { (*self).peek() }
    fn discard(&mut self, count: u64) -> ReaderResult<()> { (*self).discard(count) }
    fn readbytes(&mut self, count: u64) -> ReaderResult<Cow<'de, [u8]>> { (*self).readbytes(count) }
    fn readbytes_into(&mut self, bs: &mut [u8]) -> ReaderResult<()> { (*self).readbytes_into(bs) }
    fn read_to_end(&mut self) -> ReaderResult<Cow<'de, [u8]>> { (*self).read_to_end() }
}

pub struct IOBinarySource<R: io::Read + io::Seek> {
    pub read: R,
    pub buf: Option<u8>,
}

impl<R: io::Read + io::Seek> IOBinarySource<R> {
    #[inline(always)]
    pub fn new(read: R) -> Self {
        IOBinarySource { read, buf: None }
    }
}

impl<'de, R: io::Read + io::Seek> BinarySource<'de> for IOBinarySource<R> {
    #[inline(always)]
    fn mark(&mut self) -> io::Result<usize> {
        let pos = self.read.stream_position()? - (if self.buf.is_some() { 1 } else { 0 });
        Ok(pos as usize)
    }

    #[inline(always)]
    fn restore(&mut self, mark: usize) -> io::Result<()> {
        self.read.seek(io::SeekFrom::Start(mark as u64))?;
        self.buf = None;
        Ok(())
    }

    fn input_position(&mut self) -> Option<usize> {
        self.mark().ok()
    }

    #[inline(always)]
    fn skip(&mut self) -> io::Result<()> {
        if self.buf.is_none() { unreachable!(); }
        self.buf = None;
        Ok(())
    }

    #[inline(always)]
    fn peek(&mut self) -> io::Result<Option<u8>> {
        match self.buf {
            Some(b) => Ok(Some(b)),
            None => {
                let b = &mut [0];
                match self.read.read(b)? {
                    0 => Ok(None),
                    1 => {
                        self.buf = Some(b[0]);
                        Ok(Some(b[0]))
                    }
                    _ => unreachable!(),
                }
            }
        }
    }

    fn discard(&mut self, mut count: u64) -> ReaderResult<()> {
        if self.buf.is_some() { unreachable!(); }
        while count > i64::MAX as u64 {
            self.read.seek(io::SeekFrom::Current(i64::MAX))?;
            count -= i64::MAX as u64;
        }
        self.read.seek(io::SeekFrom::Current(count as i64))?;
        Ok(())
    }

    fn readbytes(&mut self, count: u64) -> ReaderResult<Cow<'de, [u8]>> {
        let mut bs = vec![0; count as usize];
        self.readbytes_into(&mut bs)?;
        Ok(Cow::Owned(bs))
    }

    fn readbytes_into(&mut self, bs: &mut [u8]) -> ReaderResult<()> {
        if self.buf.is_some() { unreachable!(); }
        Ok(self.read.read_exact(bs)?)
    }

    fn read_to_end(&mut self) -> ReaderResult<Cow<'de, [u8]>> {
        if self.buf.is_some() { unreachable!(); }
        let mut bs = Vec::new();
        self.read.read_to_end(&mut bs)?;
        Ok(Cow::Owned(bs))
    }
}

pub struct BytesBinarySource<'de> {
    pub bytes: &'de [u8],
    pub index: u64,
}

impl<'de> BytesBinarySource<'de> {
    #[inline(always)]
    pub fn new(bytes: &'de [u8]) -> Self {
        BytesBinarySource { bytes, index: 0 }
    }
}

impl<'de> BinarySource<'de> for BytesBinarySource<'de> {
    #[inline(always)]
    fn mark(&mut self) -> io::Result<usize> {
        Ok(self.index as usize)
    }

    #[inline(always)]
    fn restore(&mut self, mark: usize) -> io::Result<()> {
        self.index = mark as u64;
        Ok(())
    }

    fn input_position(&mut self) -> Option<usize> {
        Some(self.index as usize)
    }

    #[inline(always)]
    fn skip(&mut self) -> io::Result<()> {
        if self.index as usize >= self.bytes.len() { unreachable!(); }
        self.index += 1;
        Ok(())
    }

    #[inline(always)]
    fn peek(&mut self) -> io::Result<Option<u8>> {
        if self.index as usize >= self.bytes.len() {
            Ok(None)
        } else {
            Ok(Some(self.bytes[self.index as usize]))
        }
    }

    #[inline(always)]
    fn discard(&mut self, count: u64) -> ReaderResult<()> {
        if (self.index + count) as usize > self.bytes.len() {
            Err(self.wrap_syntax_error(SyntaxError::eof()))
        } else {
            self.index += count;
            Ok(())
        }
    }

    #[inline(always)]
    fn readbytes(&mut self, count: u64) -> ReaderResult<Cow<'de, [u8]>> {
        let base = self.index as usize;
        let limit = base + count as usize;
        if limit > self.bytes.len() {
            Err(self.wrap_syntax_error(SyntaxError::eof()))
        } else {
            let bs = &self.bytes[base..limit];
            self.index += count;
            Ok(Cow::Borrowed(bs))
        }
    }

    #[inline(always)]
    fn readbytes_into(&mut self, bs: &mut [u8]) -> ReaderResult<()> {
        let base = self.index as usize;
        let count = bs.len();
        let limit = base + count;
        if limit > self.bytes.len() {
            Err(self.wrap_syntax_error(SyntaxError::eof()))
        } else {
            bs.copy_from_slice(&self.bytes[base..limit]);
            self.index += count as u64;
            Ok(())
        }
    }

    #[inline(always)]
    fn read_to_end(&mut self) -> ReaderResult<Cow<'de, [u8]>> {
        self.readbytes(self.bytes.len() as u64 - self.index)
    }
}