From 6ecbf094091c408c4eaa1c3b69d2381910e4d147 Mon Sep 17 00:00:00 2001 From: Leonard Lesinski <84378319+Le0X8@users.noreply.github.com> Date: Fri, 2 Aug 2024 16:15:01 +0200 Subject: [PATCH] fix!: Fixed #23 --- src/archive.rs | 24 ++++++++++++----- src/file.rs | 21 +++++++++++++++ src/formats/zip.rs | 12 ++++----- src/formats/zip/writer.rs | 8 +++--- tests/zip-external.rs | 54 ++++++++++++++++++++++++++++++--------- tests/zip.rs | 6 ++--- 6 files changed, 93 insertions(+), 32 deletions(-) diff --git a/src/archive.rs b/src/archive.rs index ff318ee..acbc711 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -117,15 +117,24 @@ pub fn extract( Ok(()) } -pub struct EntrySource<'a> { +pub struct EntrySource { pub path: String, - pub source: &'a mut FsFile, + pub source: FsFile, +} + +impl Clone for EntrySource { + fn clone(&self) -> Self { + Self { + path: self.path.clone(), + source: self.source.clone(), + } + } } pub fn create( format: Formats, output: String, - input: &mut [EntrySource], + input: Vec, buffer_size: u64, ) -> Result<(), String> { let mut file = FileWriter::new(&output, &false); @@ -133,7 +142,8 @@ pub fn create( match format { Formats::Zip => { let files: Vec = input - .iter_mut() + .iter() + .cloned() .map(|entry| { if entry.source.is_directory { return ZipFile { @@ -147,9 +157,9 @@ pub fn create( }; }; let size = entry.source.size.to_owned(); - let reader = entry.source.reader.as_mut().unwrap(); + let mut reader = entry.source.reader.unwrap(); ZipFile { - checksum: crc32::hash(reader, &0, &size, &buffer_size), + checksum: crc32::hash(&mut reader, &0, &size, &buffer_size), path: entry.path.clone(), offset: 0, size, @@ -161,7 +171,7 @@ pub fn create( .collect(); formats::zip::writer::write( &mut file, - &mut formats::zip::ZipArchiveData { files }, + formats::zip::ZipArchiveData { files }, &buffer_size, ); } diff --git a/src/file.rs b/src/file.rs index 4da6a99..f44fd30 100644 --- a/src/file.rs +++ b/src/file.rs @@ -16,6 +16,17 @@ pub struct FsFile { pub is_directory: bool, } +impl Clone for FsFile { + fn clone(&self) -> Self { + Self { + size: self.size, + reader: self.reader.clone(), + modified: self.modified, + is_directory: self.is_directory, + } + } +} + impl FsFile { pub fn new(path: &String) -> Self { if fs::metadata(path).unwrap().is_dir() { @@ -227,6 +238,16 @@ impl<'a> FileReader { } } +impl Clone for FileReader { + fn clone(&self) -> Self { + Self { + path: self.path.clone(), + file: OpenOptions::new().read(true).open(&self.path).unwrap(), + pos: self.pos, + } + } +} + #[derive(Debug)] pub struct FileWriter { path: String, diff --git a/src/formats/zip.rs b/src/formats/zip.rs index 41e86e2..76372ef 100644 --- a/src/formats/zip.rs +++ b/src/formats/zip.rs @@ -141,17 +141,17 @@ pub fn to_zip_entries<'a>(from: Vec<&'a (dyn FileEntry<'a> + 'a)>) -> Vec { +pub struct ZipFile { pub path: String, pub offset: u64, pub size: u64, pub modified: DateTime, pub is_directory: bool, - pub source: Option<&'a mut FileReader>, + pub source: Option, pub checksum: u32, } -impl File for ZipFile<'_> { +impl File for ZipFile { fn get_path(&self) -> &String { &self.path } @@ -174,7 +174,7 @@ impl File for ZipFile<'_> { fn get_source(&mut self) -> Option<&mut FileReader> { match &mut self.source { - Some(source) => Some(*source), + Some(source) => Some(source), None => None, } } @@ -185,6 +185,6 @@ impl File for ZipFile<'_> { } #[derive(Debug)] -pub struct ZipArchiveData<'a> { - pub files: Vec>, +pub struct ZipArchiveData { + pub files: Vec, } diff --git a/src/formats/zip/writer.rs b/src/formats/zip/writer.rs index 41fdb44..e06f2b9 100644 --- a/src/formats/zip/writer.rs +++ b/src/formats/zip/writer.rs @@ -1,8 +1,8 @@ use super::ZipArchiveData; use crate::{file::FileWriter, helpers::datetime::msdos}; -pub fn write(target: &mut FileWriter, data: &mut ZipArchiveData, buffer_size: &u64) { - for file in &mut data.files { +pub fn write(target: &mut FileWriter, data: ZipArchiveData, buffer_size: &u64) { + for file in data.files { if file.is_directory { todo!(); } @@ -35,12 +35,14 @@ pub fn write(target: &mut FileWriter, data: &mut ZipArchiveData, buffer_size: &u target.write_utf8(name); target.write_u8array(extra); - file.source.as_mut().unwrap().export( + let mut source = file.source.unwrap(); + source.export( &file.offset, &file.size, target, &file.modified, buffer_size, ); + source.close(); } } diff --git a/tests/zip-external.rs b/tests/zip-external.rs index 6bd3eb9..4acee78 100644 --- a/tests/zip-external.rs +++ b/tests/zip-external.rs @@ -167,9 +167,9 @@ fn create_000_metadata() { archive::create( Formats::Zip, "tests/samples/zip/c000-external.zip".to_string(), - &mut [EntrySource { + vec![EntrySource { path: "test.txt".to_string(), - source: &mut FsFile::new(&"tests/samples/zip/c000-external/test.txt".to_string()), + source: FsFile::new(&"tests/samples/zip/c000-external/test.txt".to_string()), }], 1024, ) @@ -204,20 +204,12 @@ fn create_000_extract() { test_txt.write(b"Hello, world!\n"); test_txt.close(); - std::fs::create_dir_all("tests/samples/zip/c000-external2").unwrap(); - let mut test_txt = FileWriter::new( - &"tests/samples/zip/c000-external2/test.txt".to_string(), - &false, - ); - test_txt.write(b"Hello, world!\n"); - test_txt.close(); - archive::create( Formats::Zip, "tests/samples/zip/c000-external2.zip".to_string(), - &mut [EntrySource { + vec![EntrySource { path: "test.txt".to_string(), - source: &mut FsFile::new(&"tests/samples/zip/c000-external2/test.txt".to_string()), + source: FsFile::new(&"tests/samples/zip/c000-external2/test.txt".to_string()), }], 1024, ) @@ -244,3 +236,41 @@ fn create_000_extract() { std::fs::remove_dir_all("tests/samples/zip/c000-external2").unwrap(); std::fs::remove_file("tests/samples/zip/c000-external2.zip").unwrap(); } + +#[test] +fn create_000_with_iter() { + std::fs::create_dir_all("tests/samples/zip/c000-external3").unwrap(); // this is has another name to avoid conflicts + let mut test_txt = FileWriter::new( + &"tests/samples/zip/c000-external3/test.txt".to_string(), + &false, + ); + test_txt.write(b"Hello, world!\n"); + test_txt.close(); + + let input = "tests/samples/zip/c000-external3/test.txt:test.txt"; + let files: Vec = input // implementation from the CLI + .split(';') + .map(|file| { + let file = file.split(':').collect::>(); + let source_path = file.first().unwrap(); + let mut target_path = source_path; + if let Some(path) = file.get(1) { + target_path = path; + } + EntrySource { + path: target_path.to_string(), + source: FsFile::new(&source_path.to_string()), + } + }) + .collect(); + archive::create( + Formats::Zip, + "tests/samples/zip/c000-external3.zip".to_string(), + files, + 1024, + ) + .unwrap(); + + std::fs::remove_dir_all("tests/samples/zip/c000-external3").unwrap(); + std::fs::remove_file("tests/samples/zip/c000-external3.zip").unwrap(); +} diff --git a/tests/zip.rs b/tests/zip.rs index 1ca08f9..c925e15 100644 --- a/tests/zip.rs +++ b/tests/zip.rs @@ -174,7 +174,7 @@ fn create_000() { let size = input.get_size(); corelib::formats::zip::writer::write( &mut output, - &mut ZipArchiveData { + ZipArchiveData { files: vec![ZipFile { checksum: crc32::hash(&mut input, &0, &size, &1024), path: "test.txt".to_string(), @@ -182,13 +182,11 @@ fn create_000() { size, modified: input.get_times().modified, is_directory: false, - source: Some(&mut input), + source: Some(input), }], }, &1024, ); - input.close(); - output.close(); let mut file = FileReader::new(&"tests/samples/zip/c000.zip".to_string());