use std::error::Error;
use std::fmt;
use std::io;
use std::io::Read;
use std::result::Result;
use std::str::{Utf8Error, from_utf8};
use byteorder;
use byteorder::ReadBytesExt;
use super::Marker;
#[path = "decode/value_ref.rs"]
pub mod value_ref;
pub use self::value_ref::read_value_ref;
#[derive(Debug)]
pub enum ReadError {
UnexpectedEOF,
Io(io::Error),
}
impl Error for ReadError {
fn description(&self) -> &str {
match *self {
ReadError::UnexpectedEOF => "unexpected end of file while reading MessagePack value",
ReadError::Io(ref err) => err.description(),
}
}
fn cause(&self) -> Option<&Error> {
match *self {
ReadError::UnexpectedEOF => None,
ReadError::Io(ref err) => Some(err),
}
}
}
impl fmt::Display for ReadError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.description().fmt(f)
}
}
impl From<io::Error> for ReadError {
fn from(err: io::Error) -> ReadError {
ReadError::Io(err)
}
}
impl From<byteorder::Error> for ReadError {
fn from(err: byteorder::Error) -> ReadError {
match err {
byteorder::Error::UnexpectedEOF => ReadError::UnexpectedEOF,
byteorder::Error::Io(err) => ReadError::Io(err),
}
}
}
#[derive(Debug)]
pub enum MarkerReadError {
UnexpectedEOF,
Io(io::Error),
}
impl Error for MarkerReadError {
fn description(&self) -> &str {
match *self {
MarkerReadError::UnexpectedEOF => "unexpected end of file while reading MessagePack marker",
MarkerReadError::Io(ref err) => err.description(),
}
}
fn cause(&self) -> Option<&Error> {
match *self {
MarkerReadError::UnexpectedEOF => None,
MarkerReadError::Io(ref err) => Some(err),
}
}
}
impl fmt::Display for MarkerReadError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.description().fmt(f)
}
}
impl From<byteorder::Error> for MarkerReadError {
fn from(err: byteorder::Error) -> MarkerReadError {
match err {
byteorder::Error::UnexpectedEOF => MarkerReadError::UnexpectedEOF,
byteorder::Error::Io(err) => MarkerReadError::Io(err),
}
}
}
impl From<MarkerReadError> for ReadError {
fn from(err: MarkerReadError) -> ReadError {
match err {
MarkerReadError::UnexpectedEOF => ReadError::UnexpectedEOF,
MarkerReadError::Io(err) => ReadError::Io(err),
}
}
}
#[derive(Debug)]
pub enum FixedValueReadError {
UnexpectedEOF,
Io(io::Error),
TypeMismatch(Marker),
}
impl Error for FixedValueReadError {
fn description(&self) -> &str {
use self::FixedValueReadError::*;
match *self {
UnexpectedEOF => "unexpected end of file while reading MessagePack single-byte value",
Io(ref err) => err.description(),
TypeMismatch(_) => "the type decoded isn't match with the expected one",
}
}
fn cause(&self) -> Option<&Error> {
use self::FixedValueReadError::*;
match *self {
UnexpectedEOF => None,
Io(ref err) => Some(err),
TypeMismatch(_) => None,
}
}
}
impl fmt::Display for FixedValueReadError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.description().fmt(f)
}
}
impl From<MarkerReadError> for FixedValueReadError {
fn from(err: MarkerReadError) -> FixedValueReadError {
match err {
MarkerReadError::UnexpectedEOF => FixedValueReadError::UnexpectedEOF,
MarkerReadError::Io(err) => FixedValueReadError::Io(err),
}
}
}
#[derive(Debug)]
pub enum ValueReadError {
InvalidMarkerRead(ReadError),
InvalidDataRead(ReadError),
TypeMismatch(Marker),
}
impl Error for ValueReadError {
fn description(&self) -> &str {
match *self {
ValueReadError::InvalidMarkerRead(..) => "failed to read MessagePack marker",
ValueReadError::InvalidDataRead(..) => "failed to read MessagePack data",
ValueReadError::TypeMismatch(..) => "the type decoded isn't match with the expected one",
}
}
fn cause(&self) -> Option<&Error> {
match *self {
ValueReadError::InvalidMarkerRead(ref err) => Some(err),
ValueReadError::InvalidDataRead(ref err) => Some(err),
ValueReadError::TypeMismatch(..) => None,
}
}
}
impl fmt::Display for ValueReadError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.description().fmt(f)
}
}
impl From<MarkerReadError> for ValueReadError {
fn from(err: MarkerReadError) -> ValueReadError {
ValueReadError::InvalidMarkerRead(From::from(err))
}
}
#[derive(Debug)]
pub enum DecodeStringError<'a> {
InvalidMarkerRead(ReadError),
InvalidDataRead(ReadError),
TypeMismatch(Marker),
BufferSizeTooSmall(u32),
InvalidDataCopy(&'a [u8], ReadError),
InvalidUtf8(&'a [u8], Utf8Error),
}
impl<'a> Error for DecodeStringError<'a> {
fn description(&self) -> &str { "error while decoding string" }
fn cause(&self) -> Option<&Error> {
use self::DecodeStringError::*;
match *self {
InvalidMarkerRead(ref err) => Some(err),
InvalidDataRead(ref err) => Some(err),
TypeMismatch(_) => None,
BufferSizeTooSmall(_) => None,
InvalidDataCopy(_, ref err) => Some(err),
InvalidUtf8(_, ref err) => Some(err),
}
}
}
impl<'a> fmt::Display for DecodeStringError<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.description().fmt(f)
}
}
impl<'a> From<ValueReadError> for DecodeStringError<'a> {
fn from(err: ValueReadError) -> DecodeStringError<'a> {
match err {
ValueReadError::InvalidMarkerRead(err) => DecodeStringError::InvalidMarkerRead(err),
ValueReadError::InvalidDataRead(err) => DecodeStringError::InvalidDataRead(err),
ValueReadError::TypeMismatch(marker) => DecodeStringError::TypeMismatch(marker),
}
}
}
pub fn read_marker<R>(rd: &mut R) -> Result<Marker, MarkerReadError>
where R: Read
{
match rd.read_u8() {
Ok(val) => Ok(Marker::from_u8(val)),
Err(err) => Err(From::from(err)),
}
}
pub fn read_nil<R>(rd: &mut R) -> Result<(), FixedValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::Null => Ok(()),
marker => Err(FixedValueReadError::TypeMismatch(marker))
}
}
pub fn read_bool<R>(rd: &mut R) -> Result<bool, FixedValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::True => Ok(true),
Marker::False => Ok(false),
marker => Err(FixedValueReadError::TypeMismatch(marker))
}
}
pub fn read_pfix<R>(rd: &mut R) -> Result<u8, FixedValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixPos(val) => Ok(val),
marker => Err(FixedValueReadError::TypeMismatch(marker)),
}
}
pub fn read_nfix<R>(rd: &mut R) -> Result<i8, FixedValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixNeg(val) => Ok(val),
marker => Err(FixedValueReadError::TypeMismatch(marker)),
}
}
pub trait BigEndianRead: Sized {
fn read<R: Read>(rd: &mut R) -> Result<Self, byteorder::Error>;
}
impl BigEndianRead for u8 {
fn read<R: Read>(rd: &mut R) -> Result<u8, byteorder::Error> {
rd.read_u8()
}
}
impl BigEndianRead for u16 {
fn read<R: Read>(rd: &mut R) -> Result<u16, byteorder::Error> {
rd.read_u16::<byteorder::BigEndian>()
}
}
impl BigEndianRead for u32 {
fn read<R: Read>(rd: &mut R) -> Result<u32, byteorder::Error> {
rd.read_u32::<byteorder::BigEndian>()
}
}
impl BigEndianRead for u64 {
fn read<R: Read>(rd: &mut R) -> Result<u64, byteorder::Error> {
rd.read_u64::<byteorder::BigEndian>()
}
}
impl BigEndianRead for i8 {
fn read<R: Read>(rd: &mut R) -> Result<i8, byteorder::Error> {
rd.read_i8()
}
}
impl BigEndianRead for i16 {
fn read<R: Read>(rd: &mut R) -> Result<i16, byteorder::Error> {
rd.read_i16::<byteorder::BigEndian>()
}
}
impl BigEndianRead for i32 {
fn read<R: Read>(rd: &mut R) -> Result<i32, byteorder::Error> {
rd.read_i32::<byteorder::BigEndian>()
}
}
impl BigEndianRead for i64 {
fn read<R: Read>(rd: &mut R) -> Result<i64, byteorder::Error> {
rd.read_i64::<byteorder::BigEndian>()
}
}
impl BigEndianRead for f32 {
fn read<R: Read>(rd: &mut R) -> Result<f32, byteorder::Error> {
rd.read_f32::<byteorder::BigEndian>()
}
}
impl BigEndianRead for f64 {
fn read<R: Read>(rd: &mut R) -> Result<f64, byteorder::Error> {
rd.read_f64::<byteorder::BigEndian>()
}
}
pub fn read_numeric_data<R, D>(rd: &mut R) -> Result<D, ValueReadError>
where R: Read,
D: BigEndianRead
{
match D::read(rd) {
Ok(data) => Ok(data),
Err(err) => Err(ValueReadError::InvalidDataRead(From::from(err))),
}
}
#[inline]
fn read_numeric<R, D>(rd: &mut R, marker: Marker) -> Result<D, ValueReadError>
where R: Read,
D: BigEndianRead
{
match try!(read_marker(rd)) {
actual if actual == marker => read_numeric_data(rd).map_err(From::from),
marker => Err(ValueReadError::TypeMismatch(marker)),
}
}
pub fn read_u8<R>(rd: &mut R) -> Result<u8, ValueReadError>
where R: Read
{
read_numeric(rd, Marker::U8)
}
pub fn read_u16<R>(rd: &mut R) -> Result<u16, ValueReadError>
where R: Read
{
read_numeric(rd, Marker::U16)
}
pub fn read_u32<R>(rd: &mut R) -> Result<u32, ValueReadError>
where R: Read
{
read_numeric(rd, Marker::U32)
}
pub fn read_u64<R>(rd: &mut R) -> Result<u64, ValueReadError>
where R: Read
{
read_numeric(rd, Marker::U64)
}
pub fn read_i8<R>(rd: &mut R) -> Result<i8, ValueReadError>
where R: Read
{
read_numeric(rd, Marker::I8)
}
pub fn read_i16<R>(rd: &mut R) -> Result<i16, ValueReadError>
where R: Read
{
read_numeric(rd, Marker::I16)
}
pub fn read_i32<R>(rd: &mut R) -> Result<i32, ValueReadError>
where R: Read
{
read_numeric(rd, Marker::I32)
}
pub fn read_i64<R>(rd: &mut R) -> Result<i64, ValueReadError>
where R: Read
{
read_numeric(rd, Marker::I64)
}
pub fn read_u8_loosely<R>(rd: &mut R) -> Result<u8, ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixPos(val) => Ok(val),
Marker::U8 => Ok(try!(read_numeric_data(rd))),
marker => Err(ValueReadError::TypeMismatch(marker)),
}
}
pub fn read_u16_loosely<R>(rd: &mut R) -> Result<u16, ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixPos(val) => Ok(val as u16),
Marker::U8 => Ok(try!(read_numeric_data::<R, u8>(rd)) as u16),
Marker::U16 => Ok(try!(read_numeric_data(rd))),
marker => Err(ValueReadError::TypeMismatch(marker)),
}
}
pub fn read_u32_loosely<R>(rd: &mut R) -> Result<u32, ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixPos(val) => Ok(val as u32),
Marker::U8 => Ok(try!(read_numeric_data::<R, u8>(rd)) as u32),
Marker::U16 => Ok(try!(read_numeric_data::<R, u16>(rd)) as u32),
Marker::U32 => Ok(try!(read_numeric_data(rd))),
marker => Err(ValueReadError::TypeMismatch(marker)),
}
}
pub fn read_u64_loosely<R>(rd: &mut R) -> Result<u64, ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixPos(val) => Ok(val as u64),
Marker::U8 => Ok(try!(read_numeric_data::<R, u8>(rd)) as u64),
Marker::U16 => Ok(try!(read_numeric_data::<R, u16>(rd)) as u64),
Marker::U32 => Ok(try!(read_numeric_data::<R, u32>(rd)) as u64),
Marker::U64 => Ok(try!(read_numeric_data(rd))),
marker => Err(ValueReadError::TypeMismatch(marker)),
}
}
pub fn read_i8_loosely<R>(rd: &mut R) -> Result<i8, ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixNeg(val) => Ok(val),
Marker::I8 => Ok(try!(read_numeric_data(rd))),
marker => Err(ValueReadError::TypeMismatch(marker)),
}
}
pub fn read_i16_loosely<R>(rd: &mut R) -> Result<i16, ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixNeg(val) => Ok(val as i16),
Marker::I8 => Ok(try!(read_numeric_data::<R, i8>(rd)) as i16),
Marker::I16 => Ok(try!(read_numeric_data(rd))),
marker => Err(ValueReadError::TypeMismatch(marker)),
}
}
pub fn read_i32_loosely<R>(rd: &mut R) -> Result<i32, ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixNeg(val) => Ok(val as i32),
Marker::I8 => Ok(try!(read_numeric_data::<R, i8>(rd)) as i32),
Marker::I16 => Ok(try!(read_numeric_data::<R, i16>(rd)) as i32),
Marker::I32 => Ok(try!(read_numeric_data(rd))),
marker => Err(ValueReadError::TypeMismatch(marker)),
}
}
pub fn read_i64_loosely<R>(rd: &mut R) -> Result<i64, ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixNeg(val) => Ok(val as i64),
Marker::I8 => Ok(try!(read_numeric_data::<R, i8>(rd)) as i64),
Marker::I16 => Ok(try!(read_numeric_data::<R, i16>(rd)) as i64),
Marker::I32 => Ok(try!(read_numeric_data::<R, i32>(rd)) as i64),
Marker::I64 => Ok(try!(read_numeric_data(rd))),
marker => Err(ValueReadError::TypeMismatch(marker)),
}
}
use super::value::Integer;
macro_rules! make_read_int_fit {
($name:ident, $ty:ty) => {
#[allow(unused_comparisons)]
pub fn $name<R>(rd: &mut R) -> Result<$ty, ValueReadError>
where R: Read
{
let marker = try!(read_marker(rd));
let val = match marker {
Marker::FixPos(val) => Ok(Integer::U64(val as u64)),
Marker::FixNeg(val) => Ok(Integer::I64(val as i64)),
Marker::U8 => Ok(Integer::U64(try!(read_numeric_data::<R, u8>(rd)) as u64)),
Marker::I8 => Ok(Integer::I64(try!(read_numeric_data::<R, i8>(rd)) as i64)),
Marker::U16 => Ok(Integer::U64(try!(read_numeric_data::<R, u16>(rd)) as u64)),
Marker::I16 => Ok(Integer::I64(try!(read_numeric_data::<R, i16>(rd)) as i64)),
Marker::U32 => Ok(Integer::U64(try!(read_numeric_data::<R, u32>(rd)) as u64)),
Marker::I32 => Ok(Integer::I64(try!(read_numeric_data::<R, i32>(rd)) as i64)),
Marker::U64 => Ok(Integer::U64(try!(read_numeric_data::<R, u64>(rd)) as u64)),
Marker::I64 => Ok(Integer::I64(try!(read_numeric_data::<R, i64>(rd)) as i64)),
marker => Err(ValueReadError::TypeMismatch(marker)),
};
match try!(val) {
Integer::I64(v) => {
let res = v as $ty;
if v == res as i64 && (res > 0) == (v > 0) {
Ok(res)
} else {
Err(ValueReadError::TypeMismatch(marker))
}
}
Integer::U64(v) => {
let res = v as $ty;
if v == res as u64 && res >= 0 {
Ok(res)
} else {
Err(ValueReadError::TypeMismatch(marker))
}
}
}
}
}
}
make_read_int_fit!(read_i8_fit, i8);
make_read_int_fit!(read_i16_fit, i16);
make_read_int_fit!(read_i32_fit, i32);
make_read_int_fit!(read_i64_fit, i64);
make_read_int_fit!(read_u8_fit, u8);
make_read_int_fit!(read_u16_fit, u16);
make_read_int_fit!(read_u32_fit, u32);
make_read_int_fit!(read_u64_fit, u64);
pub fn read_f32<R>(rd: &mut R) -> Result<f32, ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::F32 => Ok(try!(read_numeric_data(rd))),
marker => Err(ValueReadError::TypeMismatch(marker))
}
}
pub fn read_f64<R>(rd: &mut R) -> Result<f64, ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::F64 => Ok(try!(read_numeric_data(rd))),
marker => Err(ValueReadError::TypeMismatch(marker))
}
}
pub fn read_str_len<R>(rd: &mut R) -> Result<u32, ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixStr(size) => Ok(size as u32),
Marker::Str8 => Ok(try!(read_numeric_data::<R, u8>(rd)) as u32),
Marker::Str16 => Ok(try!(read_numeric_data::<R, u16>(rd)) as u32),
Marker::Str32 => Ok(try!(read_numeric_data(rd))),
marker => Err(ValueReadError::TypeMismatch(marker))
}
}
pub fn read_str<'r, R>(rd: &mut R, mut buf: &'r mut [u8]) -> Result<&'r str, DecodeStringError<'r>>
where R: Read
{
let len = try!(read_str_len(rd));
let ulen = len as usize;
if buf.len() < ulen {
return Err(DecodeStringError::BufferSizeTooSmall(len))
}
read_str_data(rd, len, &mut buf[0..ulen])
}
pub fn read_str_data<'r, R>(rd: &mut R, len: u32, buf: &'r mut[u8]) -> Result<&'r str, DecodeStringError<'r>>
where R: Read
{
debug_assert_eq!(len as usize, buf.len());
match read_full(rd, buf) {
Ok(n) if n == buf.len() => {
match from_utf8(buf) {
Ok(decoded) => Ok(decoded),
Err(err) => Err(DecodeStringError::InvalidUtf8(buf, err)),
}
}
Ok(n) => Err(DecodeStringError::InvalidDataCopy(&buf[..n], ReadError::UnexpectedEOF)),
Err(err) => Err(DecodeStringError::InvalidDataRead(ReadError::Io(From::from(err)))),
}
}
pub fn read_str_ref(rd: &[u8]) -> Result<&[u8], DecodeStringError> {
let mut cur = io::Cursor::new(rd);
let len = try!(read_str_len(&mut cur));
let start = cur.position() as usize;
Ok(&rd[start .. start + len as usize])
}
pub fn read_array_size<R>(rd: &mut R) -> Result<u32, ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixArray(size) => Ok(size as u32),
Marker::Array16 => Ok(try!(read_numeric_data::<R, u16>(rd)) as u32),
Marker::Array32 => Ok(try!(read_numeric_data(rd))),
marker => Err(ValueReadError::TypeMismatch(marker))
}
}
pub fn read_map_size<R>(rd: &mut R) -> Result<u32, ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixMap(size) => Ok(size as u32),
Marker::Map16 => Ok(try!(read_numeric_data::<R, u16>(rd)) as u32),
Marker::Map32 => Ok(try!(read_numeric_data(rd))),
marker => Err(ValueReadError::TypeMismatch(marker))
}
}
pub fn read_bin_len<R>(rd: &mut R) -> Result<u32, ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::Bin8 => Ok(try!(read_numeric_data::<R, u8>(rd)) as u32),
Marker::Bin16 => Ok(try!(read_numeric_data::<R, u16>(rd)) as u32),
Marker::Bin32 => Ok(try!(read_numeric_data(rd))),
marker => Err(ValueReadError::TypeMismatch(marker))
}
}
pub fn read_bin_borrow(rd: &[u8]) -> Result<&[u8], ValueReadError> {
let mut cur = io::Cursor::new(rd);
let len = try!(read_bin_len(&mut cur)) as usize;
let pos = cur.position() as usize;
if rd.len() < pos + len {
Err(ValueReadError::InvalidDataRead(ReadError::UnexpectedEOF))
} else {
Ok(&rd[pos .. pos + len])
}
}
pub fn read_fixext1<R>(rd: &mut R) -> Result<(i8, u8), ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixExt1 => {
let ty = try!(read_numeric_data(rd));
let data = try!(read_numeric_data(rd));
Ok((ty, data))
}
marker => Err(ValueReadError::TypeMismatch(marker))
}
}
pub fn read_fixext2<R>(rd: &mut R) -> Result<(i8, [u8; 2]), ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixExt2 => {
let mut buf = [0; 2];
read_fixext_data(rd, &mut buf).map(|ty| (ty, buf))
}
marker => Err(ValueReadError::TypeMismatch(marker))
}
}
pub fn read_fixext4<R>(rd: &mut R) -> Result<(i8, [u8; 4]), ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixExt4 => {
let mut buf = [0; 4];
read_fixext_data(rd, &mut buf).map(|ty| (ty, buf))
}
marker => Err(ValueReadError::TypeMismatch(marker))
}
}
pub fn read_fixext8<R>(rd: &mut R) -> Result<(i8, [u8; 8]), ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixExt8 => {
let mut buf = [0; 8];
read_fixext_data(rd, &mut buf).map(|ty| (ty, buf))
}
marker => Err(ValueReadError::TypeMismatch(marker))
}
}
pub fn read_fixext16<R>(rd: &mut R) -> Result<(i8, [u8; 16]), ValueReadError>
where R: Read
{
match try!(read_marker(rd)) {
Marker::FixExt16 => {
let mut buf = [0; 16];
read_fixext_data(rd, &mut buf).map(|ty| (ty, buf))
}
marker => Err(ValueReadError::TypeMismatch(marker))
}
}
fn read_fixext_data<R>(rd: &mut R, buf: &mut [u8]) -> Result<i8, ValueReadError>
where R: Read
{
let id = try!(read_numeric_data(rd));
match read_full(rd, buf) {
Ok(n) if n == buf.len() => Ok(id),
Ok(..) => Err(ValueReadError::InvalidDataRead(ReadError::UnexpectedEOF)),
Err(err) => Err(ValueReadError::InvalidDataRead(ReadError::Io(err))),
}
}
pub fn read_full<R: Read>(rd: &mut R, buf: &mut [u8]) -> Result<usize, io::Error> {
let mut nread = 0usize;
while nread < buf.len() {
match rd.read(&mut buf[nread..]) {
Ok(0) => return Ok(nread),
Ok(n) => nread += n,
Err(ref err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err)
}
}
Ok(nread)
}
#[derive(Debug, PartialEq)]
pub struct ExtMeta {
pub typeid: i8,
pub size: u32,
}
pub fn read_ext_meta<R>(rd: &mut R) -> Result<ExtMeta, ValueReadError>
where R: Read
{
let size = match try!(read_marker(rd)) {
Marker::FixExt1 => 1,
Marker::FixExt2 => 2,
Marker::FixExt4 => 4,
Marker::FixExt8 => 8,
Marker::FixExt16 => 16,
Marker::Ext8 => try!(read_numeric_data::<R, u8>(rd)) as u32,
Marker::Ext16 => try!(read_numeric_data::<R, u16>(rd)) as u32,
Marker::Ext32 => try!(read_numeric_data(rd)),
marker => return Err(ValueReadError::TypeMismatch(marker))
};
let typeid = try!(read_numeric_data(rd));
let meta = ExtMeta { typeid: typeid, size: size };
Ok(meta)
}
pub mod value {
use std::fmt;
use std::io::Read;
use std::result::Result;
use std::str::Utf8Error;
use super::super::Marker;
pub use super::super::value::{
Integer,
Float,
Value,
};
use super::{
ReadError,
MarkerReadError,
ValueReadError,
DecodeStringError,
read_marker,
read_numeric_data,
read_str_data,
read_full,
};
#[derive(Debug)]
pub enum Error {
InvalidMarkerRead(ReadError),
InvalidDataRead(ReadError),
TypeMismatch(Marker),
BufferSizeTooSmall(u32),
InvalidDataCopy(Vec<u8>, ReadError),
InvalidUtf8(Vec<u8>, Utf8Error),
InvalidArrayRead(Box<Error>),
InvalidMapKeyRead(Box<Error>),
InvalidMapValueRead(Box<Error>),
}
impl ::std::error::Error for Error {
fn description(&self) -> &str { "error while decoding value" }
fn cause(&self) -> Option<&::std::error::Error> {
use self::Error::*;
match *self {
InvalidMarkerRead(ref err) => Some(err),
InvalidDataRead(ref err) => Some(err),
TypeMismatch(_) => None,
BufferSizeTooSmall(_) => None,
InvalidDataCopy(_, ref err) => Some(err),
InvalidUtf8(_, ref err) => Some(err),
InvalidArrayRead(ref err) => Some(&**err),
InvalidMapKeyRead(ref err) => Some(&**err),
InvalidMapValueRead(ref err) => Some(&**err),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
::std::error::Error::description(self).fmt(f)
}
}
impl From<MarkerReadError> for Error {
fn from(err: MarkerReadError) -> Error {
Error::InvalidMarkerRead(From::from(err))
}
}
impl From<ValueReadError> for Error {
fn from(err: ValueReadError) -> Error {
match err {
ValueReadError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err),
ValueReadError::InvalidDataRead(err) => Error::InvalidDataRead(err),
ValueReadError::TypeMismatch(marker) => Error::TypeMismatch(marker),
}
}
}
impl<'a> From<DecodeStringError<'a>> for Error {
fn from(err: DecodeStringError<'a>) -> Error {
match err {
DecodeStringError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err),
DecodeStringError::InvalidDataRead(err) => Error::InvalidDataRead(err),
DecodeStringError::TypeMismatch(marker) => Error::TypeMismatch(marker),
DecodeStringError::BufferSizeTooSmall(len) => Error::BufferSizeTooSmall(len),
DecodeStringError::InvalidDataCopy(buf, err) => Error::InvalidDataCopy(buf.to_vec(), err),
DecodeStringError::InvalidUtf8(buf, err) => Error::InvalidUtf8(buf.to_vec(), err),
}
}
}
fn read_str<R>(rd: &mut R, len: u32) -> Result<String, Error>
where R: Read
{
let mut vec: Vec<u8> = (0..len).map(|_| 0u8).collect();
let mut buf = &mut vec[..];
let data = try!(read_str_data(rd, len, buf));
Ok(data.to_string())
}
fn read_array<R>(rd: &mut R, len: usize) -> Result<Vec<Value>, Error>
where R: Read
{
let mut vec = Vec::with_capacity(len);
for _ in 0..len {
match read_value(rd) {
Ok(val) => vec.push(val),
Err(err) => return Err(Error::InvalidArrayRead(Box::new(err))),
}
}
Ok(vec)
}
fn read_map<R>(rd: &mut R, len: usize) -> Result<Vec<(Value, Value)>, Error>
where R: Read
{
let mut vec = Vec::with_capacity(len);
for _ in 0..len {
let key = match read_value(rd) {
Ok(val) => val,
Err(err) => return Err(Error::InvalidMapKeyRead(Box::new(err))),
};
let value = match read_value(rd) {
Ok(val) => val,
Err(err) => return Err(Error::InvalidMapValueRead(Box::new(err))),
};
vec.push((key, value));
}
Ok(vec)
}
fn read_bin_data<R>(rd: &mut R, len: usize) -> Result<Vec<u8>, Error>
where R: Read
{
let mut vec: Vec<u8> = (0..len).map(|_| 0u8).collect();
match read_full(rd, &mut vec[..]) {
Ok(n) if n == vec.len() => Ok(vec),
Ok(..) => Err(Error::InvalidDataRead(ReadError::UnexpectedEOF)),
Err(err) => Err(Error::InvalidDataRead(ReadError::Io(err))),
}
}
fn read_ext_body<R>(rd: &mut R, len: usize) -> Result<(i8, Vec<u8>), Error>
where R: Read
{
let ty = try!(read_numeric_data(rd));
let vec = try!(read_bin_data(rd, len));
Ok((ty, vec))
}
pub fn read_value<R>(rd: &mut R) -> Result<Value, Error>
where R: Read
{
let val = match try!(read_marker(rd)) {
Marker::Null => Value::Nil,
Marker::True => Value::Boolean(true),
Marker::False => Value::Boolean(false),
Marker::FixPos(val) => Value::Integer(Integer::U64(val as u64)),
Marker::FixNeg(val) => Value::Integer(Integer::I64(val as i64)),
Marker::U8 => Value::Integer(Integer::U64(try!(read_numeric_data::<R, u8>(rd)) as u64)),
Marker::U16 => Value::Integer(Integer::U64(try!(read_numeric_data::<R, u16>(rd)) as u64)),
Marker::U32 => Value::Integer(Integer::U64(try!(read_numeric_data::<R, u32>(rd)) as u64)),
Marker::U64 => Value::Integer(Integer::U64(try!(read_numeric_data(rd)))),
Marker::I8 => Value::Integer(Integer::I64(try!(read_numeric_data::<R, i8>(rd)) as i64)),
Marker::I16 => Value::Integer(Integer::I64(try!(read_numeric_data::<R, i16>(rd)) as i64)),
Marker::I32 => Value::Integer(Integer::I64(try!(read_numeric_data::<R, i32>(rd)) as i64)),
Marker::I64 => Value::Integer(Integer::I64(try!(read_numeric_data(rd)))),
Marker::F32 => Value::Float(Float::F32(try!(read_numeric_data(rd)))),
Marker::F64 => Value::Float(Float::F64(try!(read_numeric_data(rd)))),
Marker::FixStr(len) => {
let len = len as u32;
let res = try!(read_str(rd, len));
Value::String(res)
}
Marker::Str8 => {
let len = try!(read_numeric_data::<R, u8>(rd)) as u32;
let res = try!(read_str(rd, len));
Value::String(res)
}
Marker::Str16 => {
let len = try!(read_numeric_data::<R, u16>(rd)) as u32;
let res = try!(read_str(rd, len));
Value::String(res)
}
Marker::Str32 => {
let len = try!(read_numeric_data(rd));
let res = try!(read_str(rd, len));
Value::String(res)
}
Marker::FixArray(len) => {
let len = len as usize;
let vec = try!(read_array(rd, len));
Value::Array(vec)
}
Marker::Array16 => {
let len = try!(read_numeric_data::<R, u16>(rd)) as usize;
let vec = try!(read_array(rd, len));
Value::Array(vec)
}
Marker::Array32 => {
let len = try!(read_numeric_data::<R, u32>(rd)) as usize;
let vec = try!(read_array(rd, len));
Value::Array(vec)
}
Marker::FixMap(len) => {
let len = len as usize;
let map = try!(read_map(rd, len));
Value::Map(map)
}
Marker::Map16 => {
let len = try!(read_numeric_data::<R, u16>(rd)) as usize;
let map = try!(read_map(rd, len));
Value::Map(map)
}
Marker::Map32 => {
let len = try!(read_numeric_data::<R, u32>(rd)) as usize;
let map = try!(read_map(rd, len));
Value::Map(map)
}
Marker::Bin8 => {
let len = try!(read_numeric_data::<R, u8>(rd)) as usize;
let vec = try!(read_bin_data(rd, len));
Value::Binary(vec)
}
Marker::Bin16 => {
let len = try!(read_numeric_data::<R, u16>(rd)) as usize;
let vec = try!(read_bin_data(rd, len));
Value::Binary(vec)
}
Marker::Bin32 => {
let len = try!(read_numeric_data::<R, u32>(rd)) as usize;
let vec = try!(read_bin_data(rd, len));
Value::Binary(vec)
}
Marker::FixExt1 => {
let len = 1 as usize;
let (ty, vec) = try!(read_ext_body(rd, len));
Value::Ext(ty, vec)
}
Marker::FixExt2 => {
let len = 2 as usize;
let (ty, vec) = try!(read_ext_body(rd, len));
Value::Ext(ty, vec)
}
Marker::FixExt4 => {
let len = 4 as usize;
let (ty, vec) = try!(read_ext_body(rd, len));
Value::Ext(ty, vec)
}
Marker::FixExt8 => {
let len = 8 as usize;
let (ty, vec) = try!(read_ext_body(rd, len));
Value::Ext(ty, vec)
}
Marker::FixExt16 => {
let len = 16 as usize;
let (ty, vec) = try!(read_ext_body(rd, len));
Value::Ext(ty, vec)
}
Marker::Ext8 => {
let len = try!(read_numeric_data::<R, u8>(rd)) as usize;
let (ty, vec) = try!(read_ext_body(rd, len));
Value::Ext(ty, vec)
}
Marker::Ext16 => {
let len = try!(read_numeric_data::<R, u16>(rd)) as usize;
let (ty, vec) = try!(read_ext_body(rd, len));
Value::Ext(ty, vec)
}
Marker::Ext32 => {
let len = try!(read_numeric_data::<R, u32>(rd)) as usize;
let (ty, vec) = try!(read_ext_body(rd, len));
Value::Ext(ty, vec)
}
Marker::Reserved => return Err(Error::TypeMismatch(Marker::Reserved)),
};
Ok(val)
}
}
pub use self::value::read_value;