diff options
author | boasting-squirrel <boasting.squirrel@gmail.com> | 2019-03-08 21:23:33 +0000 |
---|---|---|
committer | boasting-squirrel <boasting.squirrel@gmail.com> | 2019-03-08 21:23:33 +0000 |
commit | eec5f353ffe584fcdcd7e43670fbd30d9e9f04e3 (patch) | |
tree | bf1f40abc395fbcde8386d4344b911267d05d5ef | |
parent | Working example of tar.gz (diff) | |
download | miniserve-eec5f353ffe584fcdcd7e43670fbd30d9e9f04e3.tar.gz miniserve-eec5f353ffe584fcdcd7e43670fbd30d9e9f04e3.zip |
Refactored some code
-rw-r--r-- | src/archive.rs | 74 | ||||
-rw-r--r-- | src/listing.rs | 4 |
2 files changed, 47 insertions, 31 deletions
diff --git a/src/archive.rs b/src/archive.rs index 47af660..d9ca6e9 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -7,24 +7,6 @@ use std::path::PathBuf; use tar::Builder; use tempfile::tempdir; -#[derive(Debug)] -pub enum CompressionError { - IOError(std::io::Error), - NoneError(std::option::NoneError), -} - -impl From<std::option::NoneError> for CompressionError { - fn from(err: std::option::NoneError) -> CompressionError { - CompressionError::NoneError(err) - } -} - -impl From<std::io::Error> for CompressionError { - fn from(err: std::io::Error) -> CompressionError { - CompressionError::IOError(err) - } -} - /// Available compression methods #[derive(Debug, Deserialize, Clone)] pub enum CompressionMethod { @@ -49,40 +31,74 @@ impl CompressionMethod { } } +/// Possible errors +#[derive(Debug)] +pub enum CompressionError { + IOError(std::io::Error), + NoneError(std::option::NoneError), +} + +impl From<std::option::NoneError> for CompressionError { + fn from(err: std::option::NoneError) -> CompressionError { + CompressionError::NoneError(err) + } +} + +impl From<std::io::Error> for CompressionError { + fn from(err: std::io::Error) -> CompressionError { + CompressionError::IOError(err) + } +} + pub fn create_archive_file( method: &CompressionMethod, dir: &PathBuf, -) -> Result<(String, usize, Bytes), CompressionError> { +) -> Result<(String, Bytes), CompressionError> { match method { CompressionMethod::TarGz => tgz_compress(&dir), } } -fn tgz_compress(dir: &PathBuf) -> Result<(String, usize, Bytes), CompressionError> { +/// Compresses a given folder in .tar.gz format +fn tgz_compress(dir: &PathBuf) -> Result<(String, Bytes), CompressionError> { let src_dir = dir.display().to_string(); let inner_folder = dir.file_name()?.to_str()?; let dst_filename = format!("{}.tar", inner_folder); let dst_tgz_filename = format!("{}.gz", dst_filename); - let tmp_dir = tempdir()?; + let tar_content = tar(src_dir, dst_filename, inner_folder.to_string())?; + let gz_data = gzip(&tar_content)?; + + let mut data = Bytes::new(); + data.extend_from_slice(&gz_data); + + Ok((dst_tgz_filename, data)) +} + +/// Creates a temporary tar file of a given directory, reads it and returns its content as bytes +fn tar( + src_dir: String, + dst_filename: String, + inner_folder: String, +) -> Result<Vec<u8>, CompressionError> { + let tmp_dir = tempdir()?; let dst_filepath = tmp_dir.path().join(dst_filename.clone()); let tar_file = File::create(&dst_filepath)?; + + // Create a TAR file of src_dir let mut tar_builder = Builder::new(&tar_file); tar_builder.append_dir_all(inner_folder, src_dir)?; - tar_builder.finish()?; + tar_builder.into_inner()?; + // Read the content of the TAR file and store it as bytes let mut tar_file = OpenOptions::new().read(true).open(&dst_filepath)?; let mut tar_content = Vec::new(); - let content_length = tar_file.read_to_end(&mut tar_content).unwrap(); - - let gz_data = gzip(&mut tar_content)?; - - let mut data = Bytes::new(); - data.extend_from_slice(&gz_data); + tar_file.read_to_end(&mut tar_content)?; - Ok((dst_tgz_filename, content_length, data)) + Ok(tar_content) } +/// Compresses a stream of bytes using the GZIP algorithm fn gzip(mut data: &[u8]) -> Result<Vec<u8>, CompressionError> { let mut encoder = Encoder::new(Vec::new())?; io::copy(&mut data, &mut encoder)?; diff --git a/src/listing.rs b/src/listing.rs index 565b5bf..c9542b8 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -229,9 +229,9 @@ pub fn directory_listing<S>( if let Some(compression_method) = &download { match archive::create_archive_file(&compression_method, &dir.path) { - Ok((filename, content_length, content)) => Ok(HttpResponse::Ok() + Ok((filename, content)) => Ok(HttpResponse::Ok() .content_type("application/tar") - .content_length(content_length as u64) + .content_length(content.len() as u64) .header("Content-Transfer-Encoding", "binary") .header( "Content-Disposition", |