archiver_rs/
zip.rs

1#[cfg(feature = "zip")]
2pub use self::zip::Zip;
3
4#[cfg(feature = "zip")]
5mod zip {
6    use std::fs::{create_dir_all, File};
7    use std::io::{copy, Read, Seek};
8    use std::path::Path;
9
10    use zip::ZipArchive;
11
12    use crate::{Archive, ArchiverError, Result};
13
14    pub struct Zip<R: Read + Seek> {
15        archive: ZipArchive<R>,
16    }
17
18    impl Zip<File> {
19        pub fn open(path: &Path) -> std::io::Result<Self> {
20            let archive = File::open(path)?;
21
22            Self::new(archive)
23        }
24    }
25
26    impl<R: Read + Seek> Zip<R> {
27        pub fn new(r: R) -> std::io::Result<Self> {
28            let archive = ZipArchive::new(r)?;
29
30            Ok(Self { archive })
31        }
32    }
33
34    impl<R: Read + Seek> Archive for Zip<R> {
35        fn contains(&mut self, file: String) -> Result<bool> {
36            let result = match self.archive.by_name(&file) {
37                Ok(_) => true,
38                Err(_) => false,
39            };
40
41            Ok(result)
42        }
43
44        fn extract(&mut self, destination: &Path) -> Result<()> {
45            for i in 0..self.archive.len() {
46                let mut file = self.archive.by_index(i).unwrap();
47                let target = file.mangled_name();
48                let target = destination.join(target);
49
50                if (&*file.name()).ends_with('/') {
51                    create_dir_all(target)?;
52                } else {
53                    if let Some(p) = target.parent() {
54                        if !p.exists() {
55                            create_dir_all(&p)?;
56                        }
57                    }
58                    let mut outfile = File::create(target)?;
59                    copy(&mut file, &mut outfile)?;
60                }
61            }
62
63            Ok(())
64        }
65
66        fn extract_single(&mut self, target: &Path, file: String) -> Result<()> {
67            if let Some(p) = target.parent() {
68                if !p.exists() {
69                    create_dir_all(&p)?;
70                }
71            }
72
73            let mut f = self
74                .archive
75                .by_name(&file)
76                .map_err(|_| ArchiverError::NotFound)?;
77
78            let mut target = File::create(target)?;
79            copy(&mut f, &mut target)?;
80
81            return Ok(());
82        }
83
84        fn files(&mut self) -> Result<Vec<String>> {
85            let files = self.archive.file_names().map(|e| e.into()).collect();
86
87            Ok(files)
88        }
89
90        fn walk(&mut self, f: Box<dyn Fn(String) -> Option<String>>) -> Result<()> {
91            let files = self.files()?;
92
93            for file in files {
94                if let Some(f) = f(file.clone()) {
95                    self.extract_single(Path::new(&f), file.clone())?;
96                }
97            }
98
99            Ok(())
100        }
101    }
102}