use crate::base::read::io::entry::ZipEntryReader;
use crate::error::Result;
use crate::error::ZipError;
#[cfg(feature = "tokio")]
use crate::tokio::read::stream::Ready as TokioReady;
use futures_util::io::AsyncReadExt;
use futures_util::io::Take;
use futures_util::io::{AsyncRead, BufReader};
#[cfg(feature = "tokio")]
use tokio_util::compat::TokioAsyncReadCompatExt;
use super::io::entry::WithEntry;
use super::io::entry::WithoutEntry;
pub struct Ready<R>(R);
pub struct Reading<'a, R, E>(ZipEntryReader<'a, R, E>);
#[derive(Clone)]
pub struct ZipFileReader<S>(S);
impl<'a, R> ZipFileReader<Ready<R>>
where
R: AsyncRead + Unpin + 'a,
{
pub fn new(reader: R) -> Self {
Self(Ready(reader))
}
pub async fn next_without_entry(mut self) -> Result<Option<ZipFileReader<Reading<'a, Take<R>, WithoutEntry>>>> {
let entry = match crate::base::read::lfh(&mut self.0 .0).await? {
Some(entry) => entry,
None => return Ok(None),
};
let reader = BufReader::new(self.0 .0.take(entry.compressed_size));
let reader = ZipEntryReader::new_with_owned(reader, entry.compression, entry.compressed_size);
Ok(Some(ZipFileReader(Reading(reader))))
}
pub async fn next_with_entry(mut self) -> Result<Option<ZipFileReader<Reading<'a, Take<R>, WithEntry<'a>>>>> {
let entry = match crate::base::read::lfh(&mut self.0 .0).await? {
Some(entry) => entry,
None => return Ok(None),
};
let reader = BufReader::new(self.0 .0.take(entry.compressed_size));
let reader = ZipEntryReader::new_with_owned(reader, entry.compression, entry.compressed_size);
Ok(Some(ZipFileReader(Reading(reader.into_with_entry_owned(entry)))))
}
pub async fn into_inner(self) -> R {
self.0 .0
}
}
#[cfg(feature = "tokio")]
impl<R> ZipFileReader<TokioReady<R>>
where
R: tokio::io::AsyncRead + Unpin,
{
pub fn with_tokio(reader: R) -> ZipFileReader<TokioReady<R>> {
Self(Ready(reader.compat()))
}
}
impl<'a, R, E> ZipFileReader<Reading<'a, Take<R>, E>>
where
R: AsyncRead + Unpin,
{
pub fn reader(&self) -> &ZipEntryReader<'a, Take<R>, E> {
&self.0 .0
}
pub fn reader_mut(&mut self) -> &mut ZipEntryReader<'a, Take<R>, E> {
&mut self.0 .0
}
pub async fn done(mut self) -> Result<ZipFileReader<Ready<R>>> {
if self.0 .0.read(&mut [0; 1]).await? != 0 {
return Err(ZipError::EOFNotReached);
}
Ok(ZipFileReader(Ready(self.0 .0.into_inner().into_inner())))
}
pub async fn skip(mut self) -> Result<ZipFileReader<Ready<R>>> {
while self.0 .0.read(&mut [0; 2048]).await? != 0 {}
Ok(ZipFileReader(Ready(self.0 .0.into_inner().into_inner())))
}
}