From 86c3c6d62ae1be9fb380841074e222a6e501830b Mon Sep 17 00:00:00 2001 From: husky Date: Mon, 25 Sep 2023 13:41:03 -0700 Subject: [PATCH] fix a lot of stuff and generally make things better --- src/lib.rs | 72 +++++++++++++++++++++++++--------------------------- src/tests.rs | 18 +++++++++++++ 2 files changed, 52 insertions(+), 38 deletions(-) create mode 100644 src/tests.rs diff --git a/src/lib.rs b/src/lib.rs index 1d9e1e4..91ab64e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,7 @@ +#[cfg(test)] +mod tests; + +use std::collections::HashMap; use std::io::{BufReader, Read}; /// Struct containing information about a file, without reading the actual data of the file. @@ -25,8 +29,8 @@ pub struct FarFileInfo { /// let file_a = FarFile::new_from_file(filename, buffer); /// /// let filename_b = "file_in_archive.jpg"; -/// let size_b = 12345; -/// let offset_b = 67890; +/// let size_b = 0; +/// let offset_b = 0; /// let archive_buf = Vec::new(); // buffer containing the contents of the archive /// let file_b = FarFile::new_from_archive(filename_b, size_b, offset_b, &archive_buf); /// ``` @@ -40,18 +44,20 @@ pub struct FarFile { /// /// Should be created by one of two ways: /// 1. Calling `FarArchive::new_from_files` if creating an archive from a list of FarFile structs -/// 2. Calling `farlib::test(buffer)` if loading an archive from a file/buffer +/// 2. Calling `read_archive(buffer)` if loading an archive from a file/buffer pub struct FarArchive { pub version: u32, pub file_count: u32, pub file_list: Vec, pub file_data: Vec, + pub file_index: HashMap, } impl FarFile { /// Creates a new FarFile struct from an offset, size, and archive buffer. pub fn new_from_archive(name: impl ToString, size: u32, offset: u32, original_file: &[u8]) -> FarFile { - let mut reader = BufReader::new(&original_file[offset as usize..(offset + size) as usize]); + const HEADER_SIZE: usize = 16; + let mut reader = BufReader::new(&original_file[HEADER_SIZE + offset as usize..HEADER_SIZE + (offset + size) as usize]); let mut data = Vec::new(); reader.read_to_end(&mut data).expect("Failed to read file data"); FarFile { @@ -81,32 +87,22 @@ impl FarArchive { /// use std::fs; /// use libfar::*; /// let mut file_list = Vec::new(); - /// let file_names = fs::read_dir("files").expect("Failed to read directory"); - /// for file in file_names { - /// let file_name = file.clone().unwrap().path().file_name().unwrap().to_str().unwrap(); - /// let file_size = fs::metadata(file.clone()).expect("Failed to get file size").len(); - /// let file_data = fs::read(file.clone()).expect("Failed to read file"); - /// let file_obj = FarFile { - /// name: file_name.to_string(), - /// size: file_size as u32, - /// data: file_data - /// }; - /// file_list.push(file_obj); - /// } /// /// let archive = FarArchive::new_from_files(file_list); /// ``` pub fn new_from_files(files: Vec) -> FarArchive { let mut file_list = Vec::new(); let mut file_data = Vec::new(); + let mut file_index = HashMap::new(); let mut offset = 0; - for file in files { - offset += &file.size; + for (i, file) in files.into_iter().enumerate() { file_list.push(FarFileInfo { name: file.name.clone(), size: file.size, offset, }); + offset += &file.size; + file_index.insert(file.name.clone(), i); file_data.push(file); } FarArchive { @@ -114,6 +110,7 @@ impl FarArchive { file_count: file_list.len() as u32, file_list, file_data, + file_index, } } @@ -124,19 +121,20 @@ impl FarArchive { /// // buffer is a Vec containing the contents of a .far file /// use std::fs; /// use libfar::*; - /// let buffer = fs::read("test.far").expect("Failed to read file"); - /// let test = test(&buffer); + /// let buffer = vec![]; // buffer containing the contents of a .far file + /// let test = read_archive(&buffer); /// match test { - /// Ok(archive) => { - /// let archive = archive.load_file_data(&buffer); + /// Ok(mut archive) => { + /// archive.load_file_data(&buffer); /// } /// Err(e) => { - /// panic!("test.far is not a valid archive: {}", e); + /// panic!("test.far is not a valid archive: {:?}", e); /// } /// } /// ``` - pub fn load_file_data(self, original_file: &[u8]) -> FarArchive { + pub fn load_file_data(&mut self, original_file: &[u8]) { let mut new_file_data = Vec::new(); + let mut new_file_index = HashMap::new(); for i in 0..self.file_list.len() { new_file_data.push(FarFile::new_from_archive( self.file_list[i].name.clone(), @@ -144,13 +142,10 @@ impl FarArchive { self.file_list[i].offset, original_file, )); + new_file_index.insert(self.file_list[i].name.clone(), i); } - FarArchive { - version: self.version, - file_count: self.file_count, - file_list: self.file_list, - file_data: new_file_data, - } + self.file_data = new_file_data; + self.file_index = new_file_index; } /// Creates a buffer representing the contents of a FarArchive struct. @@ -164,9 +159,7 @@ impl FarArchive { /// use std::io::Write; /// use libfar::*; /// let archive: FarArchive = unimplemented!("Create a FarArchive struct"); - /// let buffer = archive.to_vec(); - /// let mut file = fs::File::create("test.far").expect("Failed to create file"); - /// file.write_all(&buffer).expect("Failed to write to file"); + /// let buffer = archive.to_vec(); // buffer containing the contents of the archive /// ``` pub fn to_vec(self) -> Vec { // write header @@ -223,18 +216,18 @@ impl FarArchive { /// ``` /// use std::fs; /// use libfar::*; -/// let buffer = fs::read("test.far").expect("Failed to read file"); -/// let test = test(&buffer); -/// match test { +/// let buffer = vec![]; // buffer containing the contents of a .far file +/// let archive = read_archive(&buffer); +/// match archive { /// Ok(archive) => { /// println!("test.far is a valid archive"); /// }, /// Err(e) => { -/// println!("test.far is not a valid archive: {}", e); +/// println!("test.far is not a valid archive: {:?}", e); /// } /// } /// ``` -pub fn test(file: &[u8]) -> Result { +pub fn read_archive(file: &[u8]) -> Result { let mut reader = BufReader::new(file); let mut magic = [0u8; 8]; reader.read_exact(&mut magic).unwrap(); @@ -251,6 +244,7 @@ pub fn test(file: &[u8]) -> Result { file_count: files.len() as u32, file_list: files, file_data: vec![], + file_index: Default::default(), }) } @@ -293,6 +287,7 @@ fn list_files(file: &[u8]) -> Result, FarReadError> { } /// Enum representing possible errors when reading a FarArchive. +#[derive(Debug, Clone)] pub enum FarError { /// The file is not a valid Far archive. InvalidFile, @@ -301,6 +296,7 @@ pub enum FarError { } /// Struct representing the location at which a FarArchive could no longer be read, and the associated error. +#[derive(Debug, Clone)] pub struct FarReadError { pub offset: u32, pub error: String, diff --git a/src/tests.rs b/src/tests.rs new file mode 100644 index 0000000..c11e591 --- /dev/null +++ b/src/tests.rs @@ -0,0 +1,18 @@ +use super::*; + +#[test] +fn can_read_our_own_archives() { + let file_data: Vec = vec![1,2,3,4,5]; + let file_name = "test_file"; + let file = FarFile::new_from_file(file_name, file_data.clone()); + + let archive = FarArchive::new_from_files(vec![file]); + let archive_data = archive.to_vec(); + + let mut archive = read_archive(&archive_data).expect("could not read archive"); + archive.load_file_data(&archive_data); + + let new_file = archive.file_index.get(file_name).expect("could not get file"); + let new_file = &archive.file_data[*new_file]; + assert_eq!(new_file.data, file_data); +} \ No newline at end of file