use crate::base::read::io::entry::ZipEntryReader;
use crate::error::{Result, ZipError};
use crate::file::ZipFile;
#[cfg(feature = "tokio")]
use crate::tokio::read::seek::ZipFileReader as TokioZipFileReader;
use futures_lite::io::{AsyncBufRead, AsyncSeek};
#[cfg(feature = "tokio")]
use tokio_util::compat::{Compat, TokioAsyncReadCompatExt};
use super::io::entry::{WithEntry, WithoutEntry};
#[derive(Clone)]
pub struct ZipFileReader<R> {
reader: R,
file: ZipFile,
}
impl<R> ZipFileReader<R>
where
R: AsyncBufRead + AsyncSeek + Unpin,
{
pub async fn new(mut reader: R) -> Result<ZipFileReader<R>> {
let file = crate::base::read::file(&mut reader).await?;
Ok(ZipFileReader::from_raw_parts(reader, file))
}
pub fn from_raw_parts(reader: R, file: ZipFile) -> ZipFileReader<R> {
ZipFileReader { reader, file }
}
pub fn file(&self) -> &ZipFile {
&self.file
}
pub fn inner_mut(&mut self) -> &mut R {
&mut self.reader
}
pub fn into_inner(self) -> R {
self.reader
}
pub async fn reader_without_entry(&mut self, index: usize) -> Result<ZipEntryReader<'_, R, WithoutEntry>> {
let stored_entry = self.file.entries.get(index).ok_or(ZipError::EntryIndexOutOfBounds)?;
stored_entry.seek_to_data_offset(&mut self.reader).await?;
Ok(ZipEntryReader::new_with_borrow(
&mut self.reader,
stored_entry.entry.compression(),
stored_entry.entry.compressed_size(),
))
}
pub async fn reader_with_entry(&mut self, index: usize) -> Result<ZipEntryReader<'_, R, WithEntry<'_>>> {
let stored_entry = self.file.entries.get(index).ok_or(ZipError::EntryIndexOutOfBounds)?;
stored_entry.seek_to_data_offset(&mut self.reader).await?;
let reader = ZipEntryReader::new_with_borrow(
&mut self.reader,
stored_entry.entry.compression(),
stored_entry.entry.compressed_size(),
);
Ok(reader.into_with_entry(stored_entry))
}
pub async fn into_entry<'a>(mut self, index: usize) -> Result<ZipEntryReader<'a, R, WithoutEntry>>
where
R: 'a,
{
let stored_entry = self.file.entries.get(index).ok_or(ZipError::EntryIndexOutOfBounds)?;
stored_entry.seek_to_data_offset(&mut self.reader).await?;
Ok(ZipEntryReader::new_with_owned(
self.reader,
stored_entry.entry.compression(),
stored_entry.entry.compressed_size(),
))
}
}
#[cfg(feature = "tokio")]
impl<R> ZipFileReader<Compat<R>>
where
R: tokio::io::AsyncBufRead + tokio::io::AsyncSeek + Unpin,
{
pub async fn with_tokio(reader: R) -> Result<TokioZipFileReader<R>> {
let mut reader = reader.compat();
let file = crate::base::read::file(&mut reader).await?;
Ok(ZipFileReader::from_raw_parts(reader, file))
}
}