#[cfg(doc)]
use crate::base::read::seek;
use crate::base::read::io::entry::ZipEntryReader;
use crate::error::{Result, ZipError};
use crate::file::ZipFile;
use std::sync::Arc;
use futures_lite::io::Cursor;
use super::io::entry::{WithEntry, WithoutEntry};
struct Inner {
data: Vec<u8>,
file: ZipFile,
}
#[derive(Clone)]
pub struct ZipFileReader {
inner: Arc<Inner>,
}
impl ZipFileReader {
pub async fn new(data: Vec<u8>) -> Result<ZipFileReader> {
let file = crate::base::read::file(Cursor::new(&data)).await?;
Ok(ZipFileReader::from_raw_parts(data, file))
}
pub fn from_raw_parts(data: Vec<u8>, file: ZipFile) -> ZipFileReader {
ZipFileReader { inner: Arc::new(Inner { data, file }) }
}
pub fn file(&self) -> &ZipFile {
&self.inner.file
}
pub fn data(&self) -> &[u8] {
&self.inner.data
}
pub async fn reader_without_entry(&self, index: usize) -> Result<ZipEntryReader<Cursor<&[u8]>, WithoutEntry>> {
let stored_entry = self.inner.file.entries.get(index).ok_or(ZipError::EntryIndexOutOfBounds)?;
let mut cursor = Cursor::new(&self.inner.data[..]);
stored_entry.seek_to_data_offset(&mut cursor).await?;
Ok(ZipEntryReader::new_with_owned(
cursor,
stored_entry.entry.compression(),
stored_entry.entry.compressed_size(),
))
}
pub async fn reader_with_entry(&self, index: usize) -> Result<ZipEntryReader<Cursor<&[u8]>, WithEntry<'_>>> {
let stored_entry = self.inner.file.entries.get(index).ok_or(ZipError::EntryIndexOutOfBounds)?;
let mut cursor = Cursor::new(&self.inner.data[..]);
stored_entry.seek_to_data_offset(&mut cursor).await?;
let reader = ZipEntryReader::new_with_owned(
cursor,
stored_entry.entry.compression(),
stored_entry.entry.compressed_size(),
);
Ok(reader.into_with_entry(stored_entry))
}
}