fix a lot of stuff and generally make things better

This commit is contained in:
husky 2023-09-25 13:41:03 -07:00
parent 20bac182c3
commit 86c3c6d62a
No known key found for this signature in database
GPG key ID: 6B3D8CB511646891
2 changed files with 52 additions and 38 deletions

View file

@ -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<FarFileInfo>,
pub file_data: Vec<FarFile>,
pub file_index: HashMap<String, usize>,
}
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<FarFile>) -> 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<u8> 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<u8> {
// 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<FarArchive, FarError> {
pub fn read_archive(file: &[u8]) -> Result<FarArchive, FarError> {
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<FarArchive, FarError> {
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<Vec<FarFileInfo>, 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,

18
src/tests.rs Normal file
View file

@ -0,0 +1,18 @@
use super::*;
#[test]
fn can_read_our_own_archives() {
let file_data: Vec<u8> = 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);
}