flpak/zip/
reader.rs

1use std::{
2    fs, io,
3    path::{Path, PathBuf},
4};
5
6use crate::{FileType, PathBufUtils};
7use zip::ZipArchive;
8
9pub struct Reader {
10    zip: ZipArchive<fs::File>,
11    files: Vec<crate::reader::File>,
12}
13
14impl Reader {
15    fn open(path: &Path, _options: crate::reader::Options) -> crate::reader::Result<Self> {
16        let file = fs::File::open(path).map_err(crate::reader::Error::OpeningInputFile)?;
17        let mut zip =
18            ZipArchive::new(file).map_err(|err| crate::reader::Error::Other(err.to_string()))?;
19
20        let mut files = Vec::new();
21
22        for index in 0..zip.len() {
23            let file = zip
24                .by_index(index)
25                .map_err(|err| crate::reader::Error::Other(err.to_string()))?;
26
27            let file_type = if file.is_dir() {
28                FileType::Directory
29            } else {
30                FileType::RegularFile
31            };
32
33            files.push(crate::reader::File {
34                name: PathBuf::from_unix(file.name()),
35                file_type,
36                size: Some(file.size()),
37            });
38        }
39
40        Ok(Self { zip, files })
41    }
42}
43
44impl crate::reader::Reader for Reader {
45    fn file_count(&self) -> usize {
46        self.files.len()
47    }
48
49    fn get_file(&self, index: usize) -> crate::reader::File {
50        let file = self
51            .files
52            .get(index)
53            .expect("should be able to get file by index");
54
55        crate::reader::File {
56            name: file.name.clone(),
57            file_type: file.file_type.clone(),
58            size: file.size,
59        }
60    }
61
62    fn create_file_reader<'a>(
63        &'a mut self,
64        index: usize,
65    ) -> crate::reader::Result<Box<dyn io::Read + 'a>> {
66        let file = self
67            .zip
68            .by_index(index)
69            .expect("should be able to get file by index");
70
71        Ok(Box::new(file))
72    }
73}
74
75pub fn make_reader(
76    path: &Path,
77    options: crate::reader::Options,
78) -> crate::reader::Result<Box<dyn crate::reader::Reader>> {
79    Ok(Box::new(Reader::open(path, options)?))
80}