extern crate flate2; extern crate futures; extern crate tokio_io; use flate2::read::{GzDecoder, MultiGzDecoder}; use futures::prelude::*; use futures::task; use std::cmp; use std::fs::File; use std::io::{self, Read}; use tokio_io::io::read_to_end; use tokio_io::AsyncRead; struct BadReader { reader: T, x: bool, } impl BadReader { fn new(reader: T) -> BadReader { BadReader { reader, x: true } } } impl Read for BadReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { if self.x { self.x = false; let len = cmp::min(buf.len(), 1); self.reader.read(&mut buf[..len]) } else { self.x = true; Err(io::ErrorKind::WouldBlock.into()) } } } struct AssertAsync(T); impl Read for AssertAsync { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } } impl AsyncRead for AssertAsync {} struct AlwaysNotify(T); impl Future for AlwaysNotify { type Item = T::Item; type Error = T::Error; fn poll(&mut self) -> Poll { let ret = self.0.poll(); if let Ok(Async::NotReady) = &ret { task::current().notify(); } ret } } #[test] fn test_gz_asyncread() { let f = File::open("tests/good-file.gz").unwrap(); let fut = read_to_end(AssertAsync(GzDecoder::new(BadReader::new(f))), Vec::new()); let (_, content) = AlwaysNotify(fut).wait().unwrap(); let mut expected = Vec::new(); File::open("tests/good-file.txt") .unwrap() .read_to_end(&mut expected) .unwrap(); assert_eq!(content, expected); } #[test] fn test_multi_gz_asyncread() { let f = File::open("tests/multi.gz").unwrap(); let fut = read_to_end( AssertAsync(MultiGzDecoder::new(BadReader::new(f))), Vec::new(), ); let (_, content) = AlwaysNotify(fut).wait().unwrap(); let mut expected = Vec::new(); File::open("tests/multi.txt") .unwrap() .read_to_end(&mut expected) .unwrap(); assert_eq!(content, expected); }