async_zip/base/read/
seek.rs1use crate::base::read::io::entry::ZipEntryReader;
30use crate::error::{Result, ZipError};
31use crate::file::ZipFile;
32
33#[cfg(feature = "tokio")]
34use crate::tokio::read::seek::ZipFileReader as TokioZipFileReader;
35
36use futures_lite::io::{AsyncBufRead, AsyncSeek};
37
38#[cfg(feature = "tokio")]
39use tokio_util::compat::{Compat, TokioAsyncReadCompatExt};
40
41use super::io::entry::{WithEntry, WithoutEntry};
42
43#[derive(Clone)]
45pub struct ZipFileReader<R> {
46 reader: R,
47 file: ZipFile,
48}
49
50impl<R> ZipFileReader<R>
51where
52 R: AsyncBufRead + AsyncSeek + Unpin,
53{
54 pub async fn new(mut reader: R) -> Result<ZipFileReader<R>> {
56 let file = crate::base::read::file(&mut reader).await?;
57 Ok(ZipFileReader::from_raw_parts(reader, file))
58 }
59
60 pub fn from_raw_parts(reader: R, file: ZipFile) -> ZipFileReader<R> {
64 ZipFileReader { reader, file }
65 }
66
67 pub fn file(&self) -> &ZipFile {
69 &self.file
70 }
71
72 pub fn inner_mut(&mut self) -> &mut R {
76 &mut self.reader
77 }
78
79 pub fn into_inner(self) -> R {
81 self.reader
82 }
83
84 pub async fn reader_without_entry(&mut self, index: usize) -> Result<ZipEntryReader<'_, R, WithoutEntry>> {
86 let stored_entry = self.file.entries.get(index).ok_or(ZipError::EntryIndexOutOfBounds)?;
87 stored_entry.seek_to_data_offset(&mut self.reader).await?;
88
89 Ok(ZipEntryReader::new_with_borrow(
90 &mut self.reader,
91 stored_entry.entry.compression(),
92 stored_entry.entry.compressed_size(),
93 ))
94 }
95
96 pub async fn reader_with_entry(&mut self, index: usize) -> Result<ZipEntryReader<'_, R, WithEntry<'_>>> {
98 let stored_entry = self.file.entries.get(index).ok_or(ZipError::EntryIndexOutOfBounds)?;
99
100 stored_entry.seek_to_data_offset(&mut self.reader).await?;
101
102 let reader = ZipEntryReader::new_with_borrow(
103 &mut self.reader,
104 stored_entry.entry.compression(),
105 stored_entry.entry.compressed_size(),
106 );
107
108 Ok(reader.into_with_entry(stored_entry))
109 }
110
111 pub async fn into_entry<'a>(mut self, index: usize) -> Result<ZipEntryReader<'a, R, WithoutEntry>>
114 where
115 R: 'a,
116 {
117 let stored_entry = self.file.entries.get(index).ok_or(ZipError::EntryIndexOutOfBounds)?;
118
119 stored_entry.seek_to_data_offset(&mut self.reader).await?;
120
121 Ok(ZipEntryReader::new_with_owned(
122 self.reader,
123 stored_entry.entry.compression(),
124 stored_entry.entry.compressed_size(),
125 ))
126 }
127}
128
129#[cfg(feature = "tokio")]
130impl<R> ZipFileReader<Compat<R>>
131where
132 R: tokio::io::AsyncBufRead + tokio::io::AsyncSeek + Unpin,
133{
134 pub async fn with_tokio(reader: R) -> Result<TokioZipFileReader<R>> {
136 let mut reader = reader.compat();
137 let file = crate::base::read::file(&mut reader).await?;
138 Ok(ZipFileReader::from_raw_parts(reader, file))
139 }
140}