mirror of
https://github.com/NinjaCheetah/rustii.git
synced 2025-06-05 23:11:02 -04:00
U8 archive unpacking command now functional
This commit is contained in:
parent
884657268b
commit
7cef25d8f0
@ -19,18 +19,18 @@ pub enum U8Error {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct U8Node {
|
||||
node_type: u8,
|
||||
name_offset: u32, // This is really type u24, so the most significant byte will be ignored.
|
||||
data_offset: u32,
|
||||
size: u32,
|
||||
pub struct U8Node {
|
||||
pub node_type: u8,
|
||||
pub name_offset: u32, // This is really type u24, so the most significant byte will be ignored.
|
||||
pub data_offset: u32,
|
||||
pub size: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct U8Archive {
|
||||
u8_nodes: Vec<U8Node>,
|
||||
file_names: Vec<String>,
|
||||
file_data: Vec<Vec<u8>>,
|
||||
pub u8_nodes: Vec<U8Node>,
|
||||
pub file_names: Vec<String>,
|
||||
pub file_data: Vec<Vec<u8>>,
|
||||
root_node_offset: u32,
|
||||
header_size: u32,
|
||||
data_offset: u32,
|
||||
|
@ -37,8 +37,59 @@ pub fn unpack_u8_archive(input: &str, output: &str) -> Result<()> {
|
||||
if !in_path.exists() {
|
||||
bail!("Source U8 archive \"{}\" could not be found.", input);
|
||||
}
|
||||
let u8_data = u8::U8Archive::from_bytes(&fs::read(in_path)?)?;
|
||||
println!("{:?}", u8_data);
|
||||
fs::write(Path::new(output), u8_data.to_bytes()?)?;
|
||||
let out_path = PathBuf::from(output);
|
||||
if out_path.exists() {
|
||||
if !out_path.is_dir() {
|
||||
bail!("A file already exists with the specified directory name!");
|
||||
}
|
||||
} else {
|
||||
fs::create_dir(&out_path).with_context(|| format!("The output directory \"{}\" could not be created.", out_path.display()))?;
|
||||
}
|
||||
let u8_archive = u8::U8Archive::from_bytes(&fs::read(in_path).with_context(|| format!("Failed to open U8 archive \"{}\" for reading.", in_path.display()))?)?;
|
||||
// This stores the path we're actively writing files to.
|
||||
let mut current_dir = out_path.clone();
|
||||
// This is the order of directory nodes we've traversed down.
|
||||
let mut parent_dirs: Vec<u32> = Vec::from([0]);
|
||||
for i in 0..u8_archive.u8_nodes.len() {
|
||||
match u8_archive.u8_nodes[i].node_type {
|
||||
1 => {
|
||||
// Code for a directory node.
|
||||
if u8_archive.u8_nodes[i].name_offset != 0 {
|
||||
// If we're already at the correct level, make a new directory and push it to
|
||||
// the parent_dirs vec.
|
||||
if u8_archive.u8_nodes[i].data_offset == *parent_dirs.last().unwrap() {
|
||||
current_dir = current_dir.join(&u8_archive.file_names[i]);
|
||||
if !current_dir.exists() {
|
||||
fs::create_dir(¤t_dir).with_context(|| format!("Failed to create directory \"{}\".", current_dir.display()))?;
|
||||
}
|
||||
parent_dirs.push(i as u32);
|
||||
}
|
||||
// Otherwise, go back up the path until we're at the correct level.
|
||||
else {
|
||||
while u8_archive.u8_nodes[i].data_offset != *parent_dirs.last().unwrap() {
|
||||
parent_dirs.pop();
|
||||
}
|
||||
parent_dirs.push(i as u32);
|
||||
current_dir = out_path.clone();
|
||||
// Rebuild current working directory, and make sure all directories in the
|
||||
// path exist.
|
||||
for dir in &parent_dirs {
|
||||
current_dir = current_dir.join(&u8_archive.file_names[*dir as usize]);
|
||||
if !current_dir.exists() {
|
||||
fs::create_dir(¤t_dir).with_context(|| format!("Failed to create directory \"{}\".", current_dir.display()))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
0 => {
|
||||
// Code for a file node.
|
||||
fs::write(current_dir.join(&u8_archive.file_names[i]), &u8_archive.file_data[i])
|
||||
.with_context(|| format!("Failed to write file \"{}\" in directory \"{}\".", u8_archive.file_names[i], current_dir.display()))?;
|
||||
},
|
||||
_ => bail!("Node at index {} has an invalid type! U8 archive cannot be unpacked.", i)
|
||||
}
|
||||
}
|
||||
println!("Successfully unpacked U8 archive to directory \"{}\"!", out_path.display());
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user