Source code

Revision control

Copy as Markdown

Other Tools

use error::Result;↩
use serde;↩
use std::io;↩
/// An optional Read trait for advanced Bincode usage.↩
///↩
/// It is highly recommended to use bincode with `io::Read` or `&[u8]` before↩
/// implementing a custom `BincodeRead`.↩
///↩
/// The forward_read_* methods are necessary because some byte sources want↩
/// to pass a long-lived borrow to the visitor and others want to pass a↩
/// transient slice.↩
pub trait BincodeRead<'storage>: io::Read {↩
/// Check that the next `length` bytes are a valid string and pass↩
/// it on to the serde reader.↩
fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>↩
where
V: serde::de::Visitor<'storage>;↩
/// Transfer ownership of the next `length` bytes to the caller.↩
fn get_byte_buffer(&mut self, length: usize) -> Result<Vec<u8>>;↩
/// Pass a slice of the next `length` bytes on to the serde reader.↩
fn forward_read_bytes<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>↩
where
V: serde::de::Visitor<'storage>;↩
}↩
/// A BincodeRead implementation for byte slices↩
pub struct SliceReader<'storage> {↩
slice: &'storage [u8],↩
}↩
/// A BincodeRead implementation for `io::Read`ers↩
pub struct IoReader<R> {↩
reader: R,↩
temp_buffer: Vec<u8>,↩
}↩
impl<'storage> SliceReader<'storage> {↩
/// Constructs a slice reader↩
pub(crate) fn new(bytes: &'storage [u8]) -> SliceReader<'storage> {↩
SliceReader { slice: bytes }↩
}↩
#[inline(always)]↩
fn get_byte_slice(&mut self, length: usize) -> Result<&'storage [u8]> {↩
if length > self.slice.len() {↩
return Err(SliceReader::unexpected_eof());↩
}↩
let (read_slice, remaining) = self.slice.split_at(length);↩
self.slice = remaining;↩
Ok(read_slice)↩
}↩
pub(crate) fn is_finished(&self) -> bool {↩
self.slice.is_empty()↩
}↩
}↩
impl<R> IoReader<R> {↩
/// Constructs an IoReadReader↩
pub(crate) fn new(r: R) -> IoReader<R> {↩
IoReader {↩
reader: r,↩
temp_buffer: vec![],↩
}↩
}↩
}↩
impl<'storage> io::Read for SliceReader<'storage> {↩
#[inline(always)]↩
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {↩
if out.len() > self.slice.len() {↩
return Err(io::ErrorKind::UnexpectedEof.into());↩
}↩
let (read_slice, remaining) = self.slice.split_at(out.len());↩
out.copy_from_slice(read_slice);↩
self.slice = remaining;↩
Ok(out.len())↩
}↩
#[inline(always)]↩
fn read_exact(&mut self, out: &mut [u8]) -> io::Result<()> {↩
self.read(out).map(|_| ())↩
}↩
}↩
impl<R: io::Read> io::Read for IoReader<R> {↩
#[inline(always)]↩
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {↩
self.reader.read(out)↩
}↩
#[inline(always)]↩
fn read_exact(&mut self, out: &mut [u8]) -> io::Result<()> {↩
self.reader.read_exact(out)↩
}↩
}↩
impl<'storage> SliceReader<'storage> {↩
#[inline(always)]↩
fn unexpected_eof() -> Box<::ErrorKind> {↩
Box::new(::ErrorKind::Io(io::Error::new(↩
io::ErrorKind::UnexpectedEof,↩
"",↩
)))↩
}↩
}↩
impl<'storage> BincodeRead<'storage> for SliceReader<'storage> {↩
#[inline(always)]↩
fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>↩
where
V: serde::de::Visitor<'storage>,↩
{↩
use ErrorKind;↩
let string = match ::std::str::from_utf8(self.get_byte_slice(length)?) {↩
Ok(s) => s,↩
Err(e) => return Err(ErrorKind::InvalidUtf8Encoding(e).into()),↩
};↩
visitor.visit_borrowed_str(string)↩
}↩
#[inline(always)]↩
fn get_byte_buffer(&mut self, length: usize) -> Result<Vec<u8>> {↩
self.get_byte_slice(length).map(|x| x.to_vec())↩
}↩
#[inline(always)]↩
fn forward_read_bytes<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>↩
where
V: serde::de::Visitor<'storage>,↩
{↩
visitor.visit_borrowed_bytes(self.get_byte_slice(length)?)↩
}↩
}↩
impl<R> IoReader<R>↩
where
R: io::Read,↩
{↩
fn fill_buffer(&mut self, length: usize) -> Result<()> {↩
self.temp_buffer.resize(length, 0);↩
self.reader.read_exact(&mut self.temp_buffer)?;↩
Ok(())↩
}↩
}↩
impl<'a, R> BincodeRead<'a> for IoReader<R>↩
where
R: io::Read,↩
{↩
fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>↩
where
V: serde::de::Visitor<'a>,↩
{↩
self.fill_buffer(length)?;↩
let string = match ::std::str::from_utf8(&self.temp_buffer[..]) {↩
Ok(s) => s,↩
Err(e) => return Err(::ErrorKind::InvalidUtf8Encoding(e).into()),↩
};↩
visitor.visit_str(string)↩
}↩
fn get_byte_buffer(&mut self, length: usize) -> Result<Vec<u8>> {↩
self.fill_buffer(length)?;↩
Ok(::std::mem::replace(&mut self.temp_buffer, Vec::new()))↩
}↩
fn forward_read_bytes<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>↩
where
V: serde::de::Visitor<'a>,↩
{↩
self.fill_buffer(length)?;↩
visitor.visit_bytes(&self.temp_buffer[..])↩
}↩
}↩
#[cfg(test)]↩
mod test {↩
use super::IoReader;↩
#[test]↩
fn test_fill_buffer() {↩
let buffer = vec![0u8; 64];↩
let mut reader = IoReader::new(buffer.as_slice());↩
reader.fill_buffer(20).unwrap();↩
assert_eq!(20, reader.temp_buffer.len());↩
reader.fill_buffer(30).unwrap();↩
assert_eq!(30, reader.temp_buffer.len());↩
reader.fill_buffer(5).unwrap();↩
assert_eq!(5, reader.temp_buffer.len());↩
}↩
}↩