Update README, slightly reduce code repetition
[ouch.git] / src / compressors / zip.rs
blob4b4dff816f1bf3d09867083276fbb959ac5fb4bc
1 use std::{io::{Cursor, Write}, path::PathBuf};
3 use walkdir::WalkDir;
5 use crate::{
6     compressors::Compressor,
7     error::{Error, OuchResult},
8     file::File,
9 };
11 use super::compressor::Entry;
13 pub struct ZipCompressor {}
15 impl ZipCompressor {
16     // TODO: this function does not seem to be working correctly ;/
17     fn make_archive_from_memory(input: File) -> OuchResult<Vec<u8>> {
18         let buffer = vec![];
19         let mut writer = zip::ZipWriter::new(std::io::Cursor::new(buffer));
21         let inner_file_path: Box<str> = input
22             .path
23             .file_stem()
24             .ok_or(
25                 // TODO: Is this reachable?
26                 Error::InvalidInput
27             )?
28             .to_string_lossy()
29             .into();
31         let options =
32             zip::write::FileOptions::default().compression_method(zip::CompressionMethod::Deflated);
34         writer.start_file(inner_file_path, options)?;
36         let input_bytes = match input.contents_in_memory {
37             Some(bytes) => bytes,
38             None => {
39                 // TODO: error description, although this block should not be
40                 // reachable
41                 return Err(Error::InvalidInput);
42             }
43         };
45         writer.write(&*input_bytes)?;
48         
49         let bytes = writer.finish().unwrap();
51         Ok(bytes.into_inner())
52     }
54     fn make_archive_from_files(input_filenames: Vec<PathBuf>) -> OuchResult<Vec<u8>> {
55         let buffer = vec![];
56         let mut writer = zip::ZipWriter::new(Cursor::new(buffer));
58         let options =
59             zip::write::FileOptions::default().compression_method(zip::CompressionMethod::Deflated);
61         for filename in input_filenames {
62             for entry in WalkDir::new(filename) {
63                 let entry = entry?;
64                 let entry_path = &entry.path();
65                 if entry_path.is_dir() {
66                     continue;
67                 }
68                 writer
69                     .start_file(
70                         entry_path.to_string_lossy(), 
71                         options
72                     )?;
73                 let file_bytes = std::fs::read(entry.path())?;
74                 writer.write(&*file_bytes)?;
75             }
76         }
77         
79         let bytes = writer.finish().unwrap();
81         Ok(bytes.into_inner())
82     }
85 impl Compressor for ZipCompressor {
86     fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
87         match from {
88             Entry::Files(filenames) => Ok(Self::make_archive_from_files(filenames)?),
89             Entry::InMemory(file) => Ok(Self::make_archive_from_memory(file)?),
90         }
91     }