|
|
@@ -1,9 +1,11 @@ |
|
|
|
use crate::{data::read, defl}; |
|
|
|
use smol_str::SmolStr; |
|
|
|
use std::{ |
|
|
|
collections::HashMap, |
|
|
|
fs, |
|
|
|
hash::{BuildHasherDefault, Hasher}, |
|
|
|
io::{self, Read}, |
|
|
|
iter::FromIterator, |
|
|
|
path::Path, |
|
|
|
pin::Pin, |
|
|
|
str::Utf8Error, |
|
|
@@ -12,13 +14,13 @@ use twox_hash::XxHash64; |
|
|
|
|
|
|
|
error_type! { |
|
|
|
pub enum ErrArc { |
|
|
|
BadFileType(String), |
|
|
|
BadFileType(SmolStr), |
|
|
|
Deflate(defl::Err) From, |
|
|
|
DuplicateFile(String), |
|
|
|
DuplicateFile(SmolStr), |
|
|
|
InvalidMagic, |
|
|
|
Io(io::Error) From, |
|
|
|
NoArchive(usize), |
|
|
|
NoFile(String), |
|
|
|
NoFile(SmolStr), |
|
|
|
ParseInt(std::num::ParseIntError) From, |
|
|
|
Utf8(Utf8Error) From, |
|
|
|
} |
|
|
@@ -45,7 +47,7 @@ pub struct File { |
|
|
|
} |
|
|
|
|
|
|
|
pub struct Arc { |
|
|
|
name_dat: String, |
|
|
|
name_dat: Vec<SmolStr>, |
|
|
|
file_dat: HashMap<u64, File>, |
|
|
|
files: FileMap<&'static str, &'static File>, |
|
|
|
} |
|
|
@@ -60,8 +62,8 @@ fn from_utf8_null(v: &[u8]) -> Result<&str, Utf8Error> { |
|
|
|
Ok(std::str::from_utf8(v)?.trim_end_matches(|c| c == '\0' || c == ' ')) |
|
|
|
} |
|
|
|
|
|
|
|
fn path_to_local(top_path: &Path, path: &Path) -> String { |
|
|
|
path.strip_prefix(top_path).unwrap().to_string_lossy().to_string() |
|
|
|
fn path_to_local(top_path: &Path, path: &Path) -> SmolStr { |
|
|
|
SmolStr::new(path.strip_prefix(top_path).unwrap().to_string_lossy()) |
|
|
|
} |
|
|
|
|
|
|
|
fn file_ref( |
|
|
@@ -103,7 +105,7 @@ impl Arc { |
|
|
|
} else if path.is_file() { |
|
|
|
Self::read_tar(&mut fs::File::open(path)?) |
|
|
|
} else { |
|
|
|
Err(ErrArc::BadFileType(path.to_string_lossy().to_string())) |
|
|
|
Err(ErrArc::BadFileType(SmolStr::new(path.to_string_lossy()))) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -112,7 +114,7 @@ impl Arc { |
|
|
|
top_path: &Path, |
|
|
|
cur_path: &Path, |
|
|
|
file_dat: &mut HashMap<u64, File>, |
|
|
|
name_map: &mut FileMap<String, u64>, |
|
|
|
name_map: &mut FileMap<SmolStr, u64>, |
|
|
|
) -> Result<(), ErrArc> { |
|
|
|
for ent in fs::read_dir(cur_path)? { |
|
|
|
let path = ent?.path(); |
|
|
@@ -166,7 +168,7 @@ impl Arc { |
|
|
|
let name = { |
|
|
|
let pfx = from_utf8_null(&head[345..500])?; |
|
|
|
let sfx = from_utf8_null(&head[0..100])?; |
|
|
|
pfx.to_owned() + sfx |
|
|
|
SmolStr::from_iter(pfx.chars().chain(sfx.chars())) |
|
|
|
}; |
|
|
|
|
|
|
|
if name_map.contains_key(&name) { |
|
|
@@ -199,16 +201,15 @@ impl Arc { |
|
|
|
|
|
|
|
fn finalize( |
|
|
|
file_dat: HashMap<u64, File>, |
|
|
|
name_map: FileMap<String, u64>, |
|
|
|
name_map: FileMap<SmolStr, u64>, |
|
|
|
) -> Result<Pin<Box<Self>>, ErrArc> { |
|
|
|
// create a flat map of names |
|
|
|
let mut refs_dat = Vec::new(); |
|
|
|
let mut name_dat = String::new(); |
|
|
|
let mut name_dat = Vec::new(); |
|
|
|
|
|
|
|
for (name, file_ref) in name_map { |
|
|
|
let name_ref = name_dat.len(); |
|
|
|
let name_ref = name_ref..name_ref + name.len(); |
|
|
|
name_dat.push_str(&name); |
|
|
|
name_dat.push(name.clone()); |
|
|
|
refs_dat.push((name_ref, file_ref)); |
|
|
|
} |
|
|
|
|
|
|
@@ -252,7 +253,7 @@ impl Vfs { |
|
|
|
.files |
|
|
|
.get(&name) |
|
|
|
.copied() |
|
|
|
.ok_or_else(|| ErrArc::NoFile(name.to_owned())) |
|
|
|
.ok_or_else(|| ErrArc::NoFile(SmolStr::new(name))) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|