use std::io::{self, BufRead, Read, BufReader, Error, ErrorKind, Write};
use std::{cmp,mem};
use super::InflateStream;
#[inline]
fn copy_from_slice(mut to: &mut [u8], from: &[u8]) {
assert_eq!(to.len(), from.len());
to.write_all(from).unwrap();
}
pub struct DeflateDecoderBuf<R> {
reader: R,
decompressor: InflateStream,
pending_output_bytes: usize,
total_in: u64,
total_out: u64,
}
impl<R: BufRead> DeflateDecoderBuf<R> {
pub fn new(reader: R) -> DeflateDecoderBuf<R> {
DeflateDecoderBuf {
reader: reader,
decompressor: InflateStream::new(),
pending_output_bytes: 0,
total_in: 0,
total_out: 0,
}
}
pub fn from_zlib(reader: R) -> DeflateDecoderBuf<R> {
DeflateDecoderBuf {
reader: reader,
decompressor: InflateStream::from_zlib(),
pending_output_bytes: 0,
total_in: 0,
total_out: 0,
}
}
pub fn from_zlib_no_checksum(reader: R) -> DeflateDecoderBuf<R> {
DeflateDecoderBuf {
reader: reader,
decompressor: InflateStream::from_zlib_no_checksum(),
pending_output_bytes: 0,
total_in: 0,
total_out: 0,
}
}
}
impl<R> DeflateDecoderBuf<R> {
#[inline]
pub fn reset(&mut self, r: R) -> R {
self.decompressor.reset();
mem::replace(&mut self.reader, r)
}
#[inline]
pub fn reset_data(&mut self) {
self.decompressor.reset()
}
#[inline]
pub fn get_ref(&self) -> &R {
&self.reader
}
#[inline]
pub fn get_mut(&mut self) -> &mut R {
&mut self.reader
}
#[inline]
pub fn into_inner(self) -> R {
self.reader
}
#[inline]
pub fn total_in(&self) -> u64 {
self.total_in
}
#[inline]
pub fn total_out(&self) -> u64 {
self.total_out
}
#[inline]
pub fn current_checksum(&self) -> u32 {
self.decompressor.current_checksum()
}
}
impl<R: BufRead> Read for DeflateDecoderBuf<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut bytes_out = 0;
if self.pending_output_bytes != 0 {
let start = if self.decompressor.pos != 0 {
self.decompressor.pos as usize - self.pending_output_bytes
} else {
self.decompressor.buffer.len() - self.pending_output_bytes
};
let bytes_to_copy = cmp::min(buf.len(), self.pending_output_bytes);
let pending_data =
&self.decompressor.buffer[start..
start + bytes_to_copy];
copy_from_slice(&mut buf[..bytes_to_copy],pending_data);
bytes_out += bytes_to_copy;
self.pending_output_bytes -= bytes_to_copy;
if self.pending_output_bytes != 0 {
self.total_out += bytes_out as u64;
return Ok(bytes_out);
}
}
let (input_bytes_read, remaining_bytes) = {
self.pending_output_bytes = 0;
let input = try!(self.reader.fill_buf());
if input.len() == 0 {
self.total_out += bytes_out as u64;
return Ok(bytes_out);
}
let (input_bytes_read, data) =
match self.decompressor.update(&input) {
Ok(res) => res,
Err(m) => return Err(Error::new(ErrorKind::Other, m))
};
let space_left = buf.len() - bytes_out;
let bytes_to_copy = cmp::min(space_left, data.len());
copy_from_slice(&mut buf[bytes_out..bytes_out + bytes_to_copy], &data[..bytes_to_copy]);
bytes_out += bytes_to_copy;
(input_bytes_read, data.len() - bytes_to_copy)
};
self.pending_output_bytes += remaining_bytes;
self.total_in += input_bytes_read as u64;
self.total_out += bytes_out as u64;
self.reader.consume(input_bytes_read);
Ok(bytes_out)
}
}
pub struct DeflateDecoder<R> {
inner: DeflateDecoderBuf<BufReader<R>>
}
impl<R: Read> DeflateDecoder<R> {
pub fn new(reader: R) -> DeflateDecoder<R> {
DeflateDecoder {
inner: DeflateDecoderBuf::new(BufReader::new(reader))
}
}
pub fn from_zlib(reader: R) -> DeflateDecoder<R> {
DeflateDecoder {
inner: DeflateDecoderBuf::from_zlib(BufReader::new(reader))
}
}
pub fn from_zlib_no_checksum(reader: R) -> DeflateDecoder<R> {
DeflateDecoder {
inner: DeflateDecoderBuf::from_zlib_no_checksum(BufReader::new(reader))
}
}
#[inline]
pub fn reset(&mut self, r: R) -> R {
self.inner.reset(BufReader::new(r)).into_inner()
}
#[inline]
pub fn get_ref(&self) -> &R {
self.inner.get_ref().get_ref()
}
#[inline]
pub fn get_mut(&mut self) -> &mut R {
self.inner.get_mut().get_mut()
}
#[inline]
pub fn into_inner(self) -> R {
self.inner.into_inner().into_inner()
}
}
impl<R> DeflateDecoder<R> {
#[inline]
pub fn reset_data(&mut self) {
self.inner.reset_data()
}
#[inline]
pub fn total_in(&self) -> u64 {
self.inner.total_in
}
#[inline]
pub fn total_out(&self) -> u64 {
self.inner.total_out
}
#[inline]
pub fn current_checksum(&self) -> u32 {
self.inner.current_checksum()
}
}
impl<R: Read> Read for DeflateDecoder<R> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf)
}
}
#[cfg(test)]
mod test {
use super::{DeflateDecoder};
use std::io::Read;
#[test]
fn deflate_reader() {
const TEST_STRING: &'static str = "Hello, world";
let encoded = vec![243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0];
let mut decoder = DeflateDecoder::new(&encoded[..]);
let mut output = Vec::new();
decoder.read_to_end(&mut output).unwrap();
assert_eq!(String::from_utf8(output).unwrap(), TEST_STRING);
assert_eq!(decoder.total_in(), encoded.len() as u64);
assert_eq!(decoder.total_out(), TEST_STRING.len() as u64);
}
#[test]
fn zlib_reader() {
const TEST_STRING: &'static str = "Hello, zlib!";
let encoded = vec![120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201,
76, 82, 4, 0, 27, 101, 4, 19];
let mut decoder = DeflateDecoder::from_zlib(&encoded[..]);
let mut output = Vec::new();
decoder.read_to_end(&mut output).unwrap();
assert_eq!(String::from_utf8(output).unwrap(), TEST_STRING);
assert_eq!(decoder.total_in(), encoded.len() as u64);
assert_eq!(decoder.total_out(), TEST_STRING.len() as u64);
}
}