use std::fs::File;
use std::io;
use std::path::Path;
use std::path::PathBuf;
use io::Read;
use io::Seek;
use zip::ZipArchive;
pub fn zip2len<R>(z: &ZipArchive<R>) -> usize
where
R: Read + Seek,
{
z.len()
}
pub fn zipnames2total_item_count<I, P>(mut zipnames: I) -> Result<usize, io::Error>
where
I: Iterator<Item = Result<P, io::Error>>,
P: AsRef<Path>,
{
zipnames.try_fold(0, |state, next| {
let arp = next?;
let f: File = File::open(arp)?;
let z: ZipArchive<_> = ZipArchive::new(f)?;
let subtot: usize = zip2len(&z);
Ok(state + subtot)
})
}
pub fn dir2zipnames<P, Z>(
dir: P,
is_zip: Z,
) -> Result<impl Iterator<Item = Result<PathBuf, io::Error>>, io::Error>
where
P: AsRef<Path>,
Z: Fn(&Path) -> bool,
{
let dirents = std::fs::read_dir(dir)?;
Ok(dirents.filter_map(move |rdirent| match rdirent {
Err(e) => Some(Err(e)),
Ok(dirent) => {
let p: PathBuf = dirent.path();
let zfile: bool = is_zip(&p);
zfile.then_some(Ok(p))
}
}))
}
pub fn is_zip_simple(p: &Path) -> bool {
let opt_os_str: Option<&_> = p.extension();
match opt_os_str {
None => false,
Some(os_str) => os_str.eq("zip"),
}
}
pub fn dir2zipnames2total_count<P, Z>(dir: P, is_zip: Z) -> Result<usize, io::Error>
where
P: AsRef<Path>,
Z: Fn(&Path) -> bool,
{
let zip_paths = dir2zipnames(dir, is_zip)?;
zipnames2total_item_count(zip_paths)
}
pub fn dir2zipnames2total_count_default<P>(dir: P) -> Result<usize, io::Error>
where
P: AsRef<Path>,
{
dir2zipnames2total_count(dir, is_zip_simple)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_zip_simple() {
assert!(is_zip_simple(Path::new("foo.zip")));
assert!(!is_zip_simple(Path::new("baz.txt")));
}
}