sos_archive/
reader.rs

1use crate::{Result, ARCHIVE_MANIFEST};
2use async_zip::tokio::read::seek::ZipFileReader;
3use serde::de::DeserializeOwned;
4use tokio::io::{AsyncBufRead, AsyncSeek};
5
6/// Read from an archive.
7pub struct Reader<R: AsyncBufRead + AsyncSeek + Unpin> {
8    archive: ZipFileReader<R>,
9}
10
11impl<R: AsyncBufRead + AsyncSeek + Unpin> Reader<R> {
12    /// Create a new reader.
13    pub async fn new(inner: R) -> Result<Self> {
14        Ok(Self {
15            archive: ZipFileReader::with_tokio(inner).await?,
16        })
17    }
18
19    /// Inner archive reader.
20    pub fn inner(&self) -> &ZipFileReader<R> {
21        &self.archive
22    }
23
24    /// Mutable inner archive reader.
25    pub fn inner_mut(&mut self) -> &mut ZipFileReader<R> {
26        &mut self.archive
27    }
28
29    /// Find an entry by name.
30    pub async fn by_name(&mut self, name: &str) -> Result<Option<Vec<u8>>> {
31        for index in 0..self.archive.file().entries().len() {
32            let entry = self.archive.file().entries().get(index).unwrap();
33            let file_name = entry.filename();
34            let file_name = file_name.as_str()?;
35            if file_name == name {
36                let mut reader =
37                    self.archive.reader_with_entry(index).await?;
38
39                let mut buffer = Vec::new();
40                reader.read_to_end_checked(&mut buffer).await?;
41                return Ok(Some(buffer));
42            }
43        }
44        Ok(None)
45    }
46
47    /// Try to find the manifest in the zip archive.
48    pub async fn find_manifest<T: DeserializeOwned>(
49        &mut self,
50    ) -> Result<Option<T>> {
51        if let Some(buffer) = self.by_name(ARCHIVE_MANIFEST).await? {
52            let manifest_entry: T = serde_json::from_slice(&buffer)?;
53            return Ok(Some(manifest_entry));
54        }
55        Ok(None)
56    }
57}