Skip to content

Commit

Permalink
Return a Result from compression instead of panicking
Browse files Browse the repository at this point in the history
Helps if you're poking around or accidentally call the wrong APIs!

Closes rust-lang#122
  • Loading branch information
alexcrichton committed Nov 7, 2017
1 parent 7e0390b commit de7d056
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ extern crate tokio_io;

pub use gz::Builder as GzBuilder;
pub use gz::Header as GzHeader;
pub use mem::{Compress, DataError, Decompress, Flush, Status};
pub use mem::{Compress, CompressError, DecompressError, Decompress, Flush, Status};
pub use crc::{Crc, CrcReader};

mod bufreader;
Expand Down
54 changes: 38 additions & 16 deletions src/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,12 @@ pub enum Flush {
/// Error returned when a decompression object finds that the input stream of
/// bytes was not a valid input stream of bytes.
#[derive(Debug)]
pub struct DataError(());
pub struct DecompressError(());

/// Error returned when a compression object is used incorrectly or otherwise
/// generates an error.
#[derive(Debug)]
pub struct CompressError(());

/// Possible status results of compressing some data or successfully
/// decompressing a block of data.
Expand Down Expand Up @@ -216,7 +221,7 @@ impl Compress {
input: &[u8],
output: &mut [u8],
flush: Flush)
-> Status {
-> Result<Status, CompressError> {
let raw = &mut *self.inner.stream_wrapper;
raw.next_in = input.as_ptr() as *mut _;
raw.avail_in = input.len() as c_uint;
Expand All @@ -233,9 +238,10 @@ impl Compress {
output.as_ptr() as usize) as u64;

match rc {
ffi::MZ_OK => Status::Ok,
ffi::MZ_BUF_ERROR => Status::BufError,
ffi::MZ_STREAM_END => Status::StreamEnd,
ffi::MZ_OK => Ok(Status::Ok),
ffi::MZ_BUF_ERROR => Ok(Status::BufError),
ffi::MZ_STREAM_END => Ok(Status::StreamEnd),
ffi::MZ_STREAM_ERROR => Err(CompressError(())),
c => panic!("unknown return code: {}", c),
}
}
Expand All @@ -252,7 +258,7 @@ impl Compress {
input: &[u8],
output: &mut Vec<u8>,
flush: Flush)
-> Status {
-> Result<Status, CompressError> {
let cap = output.capacity();
let len = output.len();

Expand Down Expand Up @@ -326,12 +332,12 @@ impl Decompress {
///
/// If the input data to this instance of `Decompress` is not a valid
/// zlib/deflate stream then this function may return an instance of
/// `DataError` to indicate that the stream of input bytes is corrupted.
/// `DecompressError` to indicate that the stream of input bytes is corrupted.
pub fn decompress(&mut self,
input: &[u8],
output: &mut [u8],
flush: Flush)
-> Result<Status, DataError> {
-> Result<Status, DecompressError> {
let raw = &mut *self.inner.stream_wrapper;
raw.next_in = input.as_ptr() as *mut u8;
raw.avail_in = input.len() as c_uint;
Expand All @@ -349,7 +355,7 @@ impl Decompress {

match rc {
ffi::MZ_DATA_ERROR |
ffi::MZ_STREAM_ERROR => Err(DataError(())),
ffi::MZ_STREAM_ERROR => Err(DecompressError(())),
ffi::MZ_OK => Ok(Status::Ok),
ffi::MZ_BUF_ERROR => Ok(Status::BufError),
ffi::MZ_STREAM_END => Ok(Status::StreamEnd),
Expand All @@ -370,12 +376,12 @@ impl Decompress {
///
/// If the input data to this instance of `Decompress` is not a valid
/// zlib/deflate stream then this function may return an instance of
/// `DataError` to indicate that the stream of input bytes is corrupted.
/// `DecompressError` to indicate that the stream of input bytes is corrupted.
pub fn decompress_vec(&mut self,
input: &[u8],
output: &mut Vec<u8>,
flush: Flush)
-> Result<Status, DataError> {
-> Result<Status, DecompressError> {
let cap = output.capacity();
let len = output.len();

Expand Down Expand Up @@ -423,17 +429,33 @@ impl Decompress {
}
}

impl Error for DataError {
fn description(&self) -> &str { "deflate data error" }
impl Error for DecompressError {
fn description(&self) -> &str { "deflate decompression error" }
}

impl From<DecompressError> for io::Error {
fn from(data: DecompressError) -> io::Error {
io::Error::new(io::ErrorKind::Other, data)
}
}

impl fmt::Display for DecompressError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.description().fmt(f)
}
}

impl Error for CompressError {
fn description(&self) -> &str { "deflate compression error" }
}

impl From<DataError> for io::Error {
fn from(data: DataError) -> io::Error {
impl From<CompressError> for io::Error {
fn from(data: CompressError) -> io::Error {
io::Error::new(io::ErrorKind::Other, data)
}
}

impl fmt::Display for DataError {
impl fmt::Display for CompressError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.description().fmt(f)
}
Expand Down
18 changes: 9 additions & 9 deletions src/zio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::io::prelude::*;
use std::io;
use std::mem;

use {Decompress, Compress, Status, Flush, DataError};
use {Decompress, Compress, Status, Flush, DecompressError};

#[derive(Debug)]
pub struct Writer<W: Write, D: Ops> {
Expand All @@ -15,33 +15,33 @@ pub trait Ops {
fn total_in(&self) -> u64;
fn total_out(&self) -> u64;
fn run(&mut self, input: &[u8], output: &mut [u8], flush: Flush)
-> Result<Status, DataError>;
-> Result<Status, DecompressError>;
fn run_vec(&mut self, input: &[u8], output: &mut Vec<u8>, flush: Flush)
-> Result<Status, DataError>;
-> Result<Status, DecompressError>;
}

impl Ops for Compress {
fn total_in(&self) -> u64 { self.total_in() }
fn total_out(&self) -> u64 { self.total_out() }
fn run(&mut self, input: &[u8], output: &mut [u8], flush: Flush)
-> Result<Status, DataError> {
Ok(self.compress(input, output, flush))
-> Result<Status, DecompressError> {
Ok(self.compress(input, output, flush).unwrap())
}
fn run_vec(&mut self, input: &[u8], output: &mut Vec<u8>, flush: Flush)
-> Result<Status, DataError> {
Ok(self.compress_vec(input, output, flush))
-> Result<Status, DecompressError> {
Ok(self.compress_vec(input, output, flush).unwrap())
}
}

impl Ops for Decompress {
fn total_in(&self) -> u64 { self.total_in() }
fn total_out(&self) -> u64 { self.total_out() }
fn run(&mut self, input: &[u8], output: &mut [u8], flush: Flush)
-> Result<Status, DataError> {
-> Result<Status, DecompressError> {
self.decompress(input, output, flush)
}
fn run_vec(&mut self, input: &[u8], output: &mut Vec<u8>, flush: Flush)
-> Result<Status, DataError> {
-> Result<Status, DecompressError> {
self.decompress_vec(input, output, flush)
}
}
Expand Down

0 comments on commit de7d056

Please sign in to comment.