1use std::fs::File;
2use std::io;
3
4use std::path::Path;
5use std::path::PathBuf;
6
7use io::Read;
8use io::Seek;
9
10use zip::ZipArchive;
11
12pub fn zip2len<R>(z: &ZipArchive<R>) -> usize
13where
14 R: Read + Seek,
15{
16 z.len()
17}
18
19pub fn zipnames2total_item_count<I, P>(mut zipnames: I) -> Result<usize, io::Error>
20where
21 I: Iterator<Item = Result<P, io::Error>>,
22 P: AsRef<Path>,
23{
24 zipnames.try_fold(0, |state, next| {
25 let arp = next?;
26 let f: File = File::open(arp)?;
27 let z: ZipArchive<_> = ZipArchive::new(f)?;
28 let subtot: usize = zip2len(&z);
29 Ok(state + subtot)
30 })
31}
32
33pub fn dir2zipnames<P, Z>(
34 dir: P,
35 is_zip: Z,
36) -> Result<impl Iterator<Item = Result<PathBuf, io::Error>>, io::Error>
37where
38 P: AsRef<Path>,
39 Z: Fn(&Path) -> bool,
40{
41 let dirents = std::fs::read_dir(dir)?;
42 Ok(dirents.filter_map(move |rdirent| match rdirent {
43 Err(e) => Some(Err(e)),
44 Ok(dirent) => {
45 let p: PathBuf = dirent.path();
46 let zfile: bool = is_zip(&p);
47 zfile.then_some(Ok(p))
48 }
49 }))
50}
51
52pub fn is_zip_simple(p: &Path) -> bool {
53 let opt_os_str: Option<&_> = p.extension();
54 match opt_os_str {
55 None => false,
56 Some(os_str) => os_str.eq("zip"),
57 }
58}
59
60pub fn dir2zipnames2total_count<P, Z>(dir: P, is_zip: Z) -> Result<usize, io::Error>
62where
63 P: AsRef<Path>,
64 Z: Fn(&Path) -> bool,
65{
66 let zip_paths = dir2zipnames(dir, is_zip)?;
67 zipnames2total_item_count(zip_paths)
68}
69
70pub fn dir2zipnames2total_count_default<P>(dir: P) -> Result<usize, io::Error>
72where
73 P: AsRef<Path>,
74{
75 dir2zipnames2total_count(dir, is_zip_simple)
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn test_is_zip_simple() {
84 assert!(is_zip_simple(Path::new("foo.zip")));
85 assert!(!is_zip_simple(Path::new("baz.txt")));
86 }
87}