(WIP) Minor misc. changes
[ouch.git] / src / compressors / zip.rs
blob453fbcb83a6b6683da29e829462fd98107c8367f
1 use std::{
2     io::{Cursor, Write},
3     path::PathBuf,
4 };
6 use walkdir::WalkDir;
8 use super::compressor::Entry;
9 use crate::{compressors::Compressor, file::File, utils};
11 pub struct ZipCompressor {}
13 impl ZipCompressor {
14     // TODO: this function does not seem to be working correctly ;/
15     fn make_archive_from_memory(input: File) -> crate::Result<Vec<u8>> {
16         let buffer = vec![];
17         let mut writer = zip::ZipWriter::new(std::io::Cursor::new(buffer));
19         let inner_file_path: Box<str> = input
20             .path
21             .file_stem()
22             .ok_or(
23                 // TODO: Is this reachable?
24                 crate::Error::InvalidInput,
25             )?
26             .to_string_lossy()
27             .into();
29         let options =
30             zip::write::FileOptions::default().compression_method(zip::CompressionMethod::Deflated);
32         writer.start_file(inner_file_path, options)?;
34         let input_bytes = match input.contents_in_memory {
35             Some(bytes) => bytes,
36             None => {
37                 // TODO: error description, although this block should not be
38                 // reachable
39                 return Err(crate::Error::InvalidInput);
40             }
41         };
43         writer.write_all(&*input_bytes)?;
45         let bytes = writer.finish().unwrap();
47         Ok(bytes.into_inner())
48     }
50     fn make_archive_from_files(input_filenames: Vec<PathBuf>) -> crate::Result<Vec<u8>> {
51         let buffer = vec![];
52         let mut writer = zip::ZipWriter::new(Cursor::new(buffer));
54         let options =
55             zip::write::FileOptions::default().compression_method(zip::CompressionMethod::Deflated);
57         for filename in input_filenames {
58             let previous_location = utils::change_dir_and_return_parent(&filename)?;
59             let filename = filename
60                 .file_name()
61                 // Safe unwrap since the function call above would fail in scenarios
62                 // where this unwrap would panic
63                 .unwrap();
65             for entry in WalkDir::new(filename) {
66                 let entry = entry?;
67                 let entry_path = &entry.path();
68                 if entry_path.is_dir() {
69                     continue;
70                 }
71                 
72                 writer.start_file(entry_path.to_string_lossy(), options)?;
73                 println!("Compressing {:?}", entry_path);
74                 let file_bytes = std::fs::read(entry.path())?;
75                 writer.write_all(&*file_bytes)?;
76             }
78             std::env::set_current_dir(previous_location)?;
79         }
81         let bytes = writer.finish()?;
83         Ok(bytes.into_inner())
84     }
87 impl Compressor for ZipCompressor {
88     fn compress(&self, from: Entry) -> crate::Result<Vec<u8>> {
89         match from {
90             Entry::Files(filenames) => Ok(Self::make_archive_from_files(filenames)?),
91             Entry::InMemory(file) => Ok(Self::make_archive_from_memory(file)?),
92         }
93     }