use std::error;
use std::fs;
use std::io;
use std::io::prelude::*;
use std::path::Path;
pub struct Unzpack;
impl Unzpack {
pub fn persist<P: AsRef<Path>>(
zip_bytes: &'static [u8],
filepath: P,
) -> Result<(), Box<dyn error::Error>> {
let mut file = fs::File::create(filepath)?;
file.write_all(zip_bytes)?;
Ok(())
}
pub fn extract<P: AsRef<Path>>(filepath: P, outdir: P) -> Result<(), Box<dyn error::Error>> {
let filepath = filepath.as_ref().canonicalize()?;
let file = fs::File::open(filepath)?;
let mut archive = zip::ZipArchive::new(file).unwrap();
let outdir = outdir.as_ref();
if !outdir.exists() {
fs::create_dir_all(&outdir)?;
}
let outdir = outdir.canonicalize()?;
if !outdir.is_dir() {
return Result::Err(From::from(format!(
"path \"{:?}\" is not a directory",
&outdir
)));
}
for i in 0..archive.len() {
let mut file = archive.by_index(i).unwrap();
let outpath = outdir.join(file.sanitized_name());
if (&*file.name()).ends_with('/') {
fs::create_dir_all(&outpath).unwrap();
} else {
if let Some(p) = outpath.parent() {
if !p.exists() {
fs::create_dir_all(&p).unwrap();
}
}
let mut outfile = fs::File::create(&outpath).unwrap();
io::copy(&mut file, &mut outfile).unwrap();
}
}
Ok(())
}
pub fn unpack<P: AsRef<Path>>(
zip_bytes: &'static [u8],
out_filepath: P,
out_dirpath: P,
) -> Result<(), Box<dyn error::Error>> {
Unzpack::persist(zip_bytes, out_filepath.as_ref())?;
Unzpack::extract(out_filepath.as_ref(), out_dirpath.as_ref())?;
fs::remove_file(out_filepath)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
const ZIP_BYTES: &[u8] = include_bytes!("/tmp/static-web-server.zip");
#[test]
fn check_zip_file() {
let filepath = Path::new("/tmp/static-web-server.zip");
assert_eq!(filepath.exists(), true);
assert_eq!(filepath.is_file(), true);
}
#[test]
fn test_persist() -> Result<(), Box<dyn error::Error>> {
let out_filepath = Path::new("/tmp/static-web-server.persist.zip");
Unzpack::persist(ZIP_BYTES, out_filepath)?;
assert_eq!(out_filepath.exists(), true);
assert_eq!(out_filepath.is_file(), true);
Ok(())
}
#[test]
fn test_extract() -> Result<(), Box<dyn error::Error>> {
let out_filepath = Path::new("/tmp/static-web-server.persist.zip");
Unzpack::persist(ZIP_BYTES, out_filepath)?;
assert_eq!(out_filepath.exists(), true);
assert_eq!(out_filepath.is_file(), true);
let out_dirpath = Path::new("/tmp/static-web-server.extract");
Unzpack::extract(out_filepath, out_dirpath)?;
assert_eq!(out_dirpath.exists(), true);
assert_eq!(out_dirpath.is_dir(), true);
Ok(())
}
#[test]
fn test_unpack() -> Result<(), Box<dyn error::Error>> {
let out_filepath = Path::new("/tmp/static-web-server.unpack.zip");
let out_dirpath = Path::new("/tmp/static-web-server.unpack");
Unzpack::unpack(ZIP_BYTES, out_filepath, out_dirpath)?;
Ok(())
}
}