use std::io;
use std::io::prelude::*;
use super::bufread;
use super::{GzBuilder, GzHeader};
use crate::bufreader::BufReader;
use crate::Compression;
#[derive(Debug)]
pub struct GzEncoder<R> {
inner: bufread::GzEncoder<BufReader<R>>,
}
pub fn gz_encoder<R: Read>(inner: bufread::GzEncoder<BufReader<R>>) -> GzEncoder<R> {
GzEncoder { inner }
}
impl<R: Read> GzEncoder<R> {
pub fn new(r: R, level: Compression) -> GzEncoder<R> {
GzBuilder::new().read(r, level)
}
}
impl<R> GzEncoder<R> {
pub fn get_ref(&self) -> &R {
self.inner.get_ref().get_ref()
}
pub fn get_mut(&mut self) -> &mut R {
self.inner.get_mut().get_mut()
}
pub fn into_inner(self) -> R {
self.inner.into_inner().into_inner()
}
}
impl<R: Read> Read for GzEncoder<R> {
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
self.inner.read(into)
}
}
impl<R: Read + Write> Write for GzEncoder<R> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.get_mut().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.get_mut().flush()
}
}
#[derive(Debug)]
pub struct GzDecoder<R> {
inner: bufread::GzDecoder<BufReader<R>>,
}
impl<R: Read> GzDecoder<R> {
pub fn new(r: R) -> GzDecoder<R> {
GzDecoder {
inner: bufread::GzDecoder::new(BufReader::new(r)),
}
}
}
impl<R> GzDecoder<R> {
pub fn header(&self) -> Option<&GzHeader> {
self.inner.header()
}
pub fn get_ref(&self) -> &R {
self.inner.get_ref().get_ref()
}
pub fn get_mut(&mut self) -> &mut R {
self.inner.get_mut().get_mut()
}
pub fn into_inner(self) -> R {
self.inner.into_inner().into_inner()
}
}
impl<R: Read> Read for GzDecoder<R> {
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
self.inner.read(into)
}
}
impl<R: Read + Write> Write for GzDecoder<R> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.get_mut().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.get_mut().flush()
}
}
#[derive(Debug)]
pub struct MultiGzDecoder<R> {
inner: bufread::MultiGzDecoder<BufReader<R>>,
}
impl<R: Read> MultiGzDecoder<R> {
pub fn new(r: R) -> MultiGzDecoder<R> {
MultiGzDecoder {
inner: bufread::MultiGzDecoder::new(BufReader::new(r)),
}
}
}
impl<R> MultiGzDecoder<R> {
pub fn header(&self) -> Option<&GzHeader> {
self.inner.header()
}
pub fn get_ref(&self) -> &R {
self.inner.get_ref().get_ref()
}
pub fn get_mut(&mut self) -> &mut R {
self.inner.get_mut().get_mut()
}
pub fn into_inner(self) -> R {
self.inner.into_inner().into_inner()
}
}
impl<R: Read> Read for MultiGzDecoder<R> {
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
self.inner.read(into)
}
}
impl<R: Read + Write> Write for MultiGzDecoder<R> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.get_mut().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.get_mut().flush()
}
}
#[cfg(test)]
mod tests {
use std::io::{Cursor, ErrorKind, Read, Result, Write};
use super::GzDecoder;
#[derive(Debug)]
pub struct BlockingCursor {
pub cursor: Cursor<Vec<u8>>,
}
impl BlockingCursor {
pub fn new() -> BlockingCursor {
BlockingCursor {
cursor: Cursor::new(Vec::new()),
}
}
pub fn set_position(&mut self, pos: u64) {
return self.cursor.set_position(pos);
}
}
impl Write for BlockingCursor {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
return self.cursor.write(buf);
}
fn flush(&mut self) -> Result<()> {
return self.cursor.flush();
}
}
impl Read for BlockingCursor {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let r = self.cursor.read(buf);
match r {
Err(ref err) => {
if err.kind() == ErrorKind::UnexpectedEof {
return Err(ErrorKind::WouldBlock.into());
}
}
Ok(0) => {
return Err(ErrorKind::WouldBlock.into());
}
Ok(_n) => {}
}
return r;
}
}
#[test]
fn blocked_partial_header_read() {
let mut r = BlockingCursor::new();
let data = vec![1, 2, 3];
match r.write_all(&data) {
Ok(()) => {}
_ => {
panic!("Unexpected result for write_all");
}
}
r.set_position(0);
let mut decoder = GzDecoder::new(r);
let mut out = Vec::with_capacity(7);
match decoder.read(&mut out) {
Err(e) => {
assert_eq!(e.kind(), ErrorKind::WouldBlock);
}
_ => {
panic!("Unexpected result for decoder.read");
}
}
}
}