use std::error;
use std::fmt;
use std::io;
use std::result;
pub type Result<T> = result::Result<T, Error>;
pub struct IntoInnerError<W> {
wtr: W,
err: io::Error,
}
pub fn new_into_inner_error<W>(wtr: W, err: io::Error) -> IntoInnerError<W> {
IntoInnerError { wtr: wtr, err: err }
}
impl<W> IntoInnerError<W> {
pub fn error(&self) -> &io::Error {
&self.err
}
pub fn into_inner(self) -> W {
self.wtr
}
}
impl<W: ::std::any::Any> error::Error for IntoInnerError<W> {
fn description(&self) -> &str {
self.err.description()
}
fn cause(&self) -> Option<&error::Error> {
self.err.cause()
}
}
impl<W> fmt::Display for IntoInnerError<W> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.err.fmt(f)
}
}
impl<W> fmt::Debug for IntoInnerError<W> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.err.fmt(f)
}
}
#[derive(Debug)]
pub enum Error {
TooBig {
given: u64,
max: u64,
},
BufferTooSmall {
given: u64,
min: u64,
},
Empty,
Header,
HeaderMismatch {
expected_len: u64,
got_len: u64,
},
Literal {
len: u64,
src_len: u64,
dst_len: u64,
},
CopyRead {
len: u64,
src_len: u64,
},
CopyWrite {
len: u64,
dst_len: u64,
},
Offset {
offset: u64,
dst_pos: u64,
},
StreamHeader {
byte: u8,
},
StreamHeaderMismatch {
bytes: Vec<u8>,
},
UnsupportedChunkType {
byte: u8,
},
UnsupportedChunkLength {
len: u64,
header: bool,
},
Checksum {
expected: u32,
got: u32,
},
}
impl From<Error> for io::Error {
fn from(err: Error) -> io::Error {
io::Error::new(io::ErrorKind::Other, err)
}
}
impl Eq for Error {}
impl PartialEq for Error {
fn eq(&self, other: &Error) -> bool {
use self::Error::*;
match (self, other) {
(&TooBig { given: given1, max: max1 },
&TooBig { given: given2, max: max2 }) => {
(given1, max1) == (given2, max2)
}
(&BufferTooSmall { given: given1, min: min1 },
&BufferTooSmall { given: given2, min: min2 }) => {
(given1, min1) == (given2, min2)
}
(&Empty, &Empty) => true,
(&Header, &Header) => true,
(&HeaderMismatch { expected_len: elen1, got_len: glen1 },
&HeaderMismatch { expected_len: elen2, got_len: glen2 }) => {
(elen1, glen1) == (elen2, glen2)
}
(&Literal { len: len1, src_len: src_len1, dst_len: dst_len1 },
&Literal { len: len2, src_len: src_len2, dst_len: dst_len2 }) => {
(len1, src_len1, dst_len1) == (len2, src_len2, dst_len2)
}
(&CopyRead { len: len1, src_len: src_len1 },
&CopyRead { len: len2, src_len: src_len2 }) => {
(len1, src_len1) == (len2, src_len2)
}
(&CopyWrite { len: len1, dst_len: dst_len1 },
&CopyWrite { len: len2, dst_len: dst_len2 }) => {
(len1, dst_len1) == (len2, dst_len2)
}
(&Offset { offset: offset1, dst_pos: dst_pos1 },
&Offset { offset: offset2, dst_pos: dst_pos2 }) => {
(offset1, dst_pos1) == (offset2, dst_pos2)
}
(&StreamHeader { byte: byte1 }, &StreamHeader { byte: byte2 }) => {
byte1 == byte2
}
(&StreamHeaderMismatch { bytes: ref bytes1 },
&StreamHeaderMismatch { bytes: ref bytes2 }) => {
bytes1 == bytes2
}
(&UnsupportedChunkType { byte: byte1 },
&UnsupportedChunkType { byte: byte2 }) => {
byte1 == byte2
}
(&UnsupportedChunkLength { len: len1, header: header1 },
&UnsupportedChunkLength { len: len2, header: header2 }) => {
(len1, header1) == (len2, header2)
}
(&Checksum { expected: e1, got: g1 },
&Checksum { expected: e2, got: g2 }) => {
(e1, g1) == (e2, g2)
}
_ => false,
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::TooBig { .. } => "snappy: input buffer too big",
Error::BufferTooSmall { .. } => "snappy: output buffer too small",
Error::Empty => "snappy: corrupt input (empty)",
Error::Header => "snappy: corrupt input (invalid header)",
Error::HeaderMismatch { .. } => "snappy: corrupt input \
(header mismatch)",
Error::Literal { .. } => "snappy: corrupt input (bad literal)",
Error::CopyRead { .. } => "snappy: corrupt input (bad copy read)",
Error::CopyWrite { .. } => "snappy: corrupt input \
(bad copy write)",
Error::Offset { .. } => "snappy: corrupt input (bad offset)",
Error::StreamHeader { .. } => {
"snappy: corrupt input (missing stream header)"
}
Error::StreamHeaderMismatch { .. } => {
"snappy: corrupt input (stream header mismatch)"
}
Error::UnsupportedChunkType { .. } => {
"snappy: corrupt input (unsupported chunk type)"
}
Error::UnsupportedChunkLength { header: false, .. } => {
"snappy: corrupt input (unsupported chunk length)"
}
Error::UnsupportedChunkLength { header: true, .. } => {
"snappy: corrupt input (invalid stream header)"
}
Error::Checksum { .. } => "snappy: corrupt input (bad checksum)",
}
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::TooBig { given, max } => {
write!(f, "snappy: input buffer (size = {}) is larger than \
allowed (size = {})", given, max)
}
Error::BufferTooSmall { given, min } => {
write!(f, "snappy: output buffer (size = {}) is smaller than \
required (size = {})", given, min)
}
Error::Empty => {
write!(f, "snappy: corrupt input (empty)")
}
Error::Header => {
write!(f, "snappy: corrupt input (invalid header)")
}
Error::HeaderMismatch { expected_len, got_len } => {
write!(f, "snappy: corrupt input (header mismatch; expected \
{} decompressed bytes but got {})",
expected_len, got_len)
}
Error::Literal { len, src_len, dst_len } => {
write!(f, "snappy: corrupt input (expected literal read of \
length {}; remaining src: {}; remaining dst: {})",
len, src_len, dst_len)
}
Error::CopyRead { len, src_len } => {
write!(f, "snappy: corrupt input (expected copy read of \
length {}; remaining src: {})", len, src_len)
}
Error::CopyWrite { len, dst_len } => {
write!(f, "snappy: corrupt input (expected copy write of \
length {}; remaining dst: {})", len, dst_len)
}
Error::Offset { offset, dst_pos } => {
write!(f, "snappy: corrupt input (expected valid offset but \
got offset {}; dst position: {})", offset, dst_pos)
}
Error::StreamHeader { byte } => {
write!(f, "snappy: corrupt input (expected stream header but \
got unexpected chunk type byte {})", byte)
}
Error::StreamHeaderMismatch { ref bytes } => {
write!(f, "snappy: corrupt input (expected sNaPpY stream \
header but got {})", escape(&**bytes))
}
Error::UnsupportedChunkType { byte } => {
write!(f, "snappy: corrupt input (unsupported chunk type: {})",
byte)
}
Error::UnsupportedChunkLength { len, header: false } => {
write!(f, "snappy: corrupt input \
(unsupported chunk length: {})", len)
}
Error::UnsupportedChunkLength { len, header: true } => {
write!(f, "snappy: corrupt input \
(invalid stream header length: {})", len)
}
Error::Checksum { expected, got } => {
write!(f, "snappy: corrupt input (bad checksum; \
expected: {}, got: {})", expected, got)
}
}
}
}
fn escape(bytes: &[u8]) -> String {
use std::ascii::escape_default;
bytes.iter().flat_map(|&b| escape_default(b)).map(|b| b as char).collect()
}