From e4ff9c0e7bee401829b1c3ead661aaed3b5ca773 Mon Sep 17 00:00:00 2001 From: patataofcourse Date: Tue, 19 Mar 2024 12:32:00 +0100 Subject: [PATCH 1/4] run formatter, remove let _ --- src/control_codes.rs | 190 ++++++++++++++++++++++------------------ src/diff_utils.rs | 96 ++++++++++++-------- src/error.rs | 6 +- src/lib.rs | 6 +- src/main.rs | 122 +++++++++++++++++--------- src/msbt.rs | 111 ++++++++++++++--------- src/structs.rs | 4 +- src/structs/atr1.rs | 38 +++++--- src/structs/header.rs | 46 +++++----- src/structs/lbl1.rs | 126 ++++++++++++++++---------- src/structs/txt2.rs | 199 ++++++++++++++++++++++++------------------ 11 files changed, 569 insertions(+), 375 deletions(-) diff --git a/src/control_codes.rs b/src/control_codes.rs index 8fafe2a..0d642be 100644 --- a/src/control_codes.rs +++ b/src/control_codes.rs @@ -5,16 +5,23 @@ use bytestream::ByteOrder; use crate::structs::txt2::{convert_char, read_char}; #[derive(Debug)] -pub struct ControlCode{ +pub struct ControlCode { tag_group: u16, tag_type: u16, params_size: u16, - params: Vec + params: Vec, } -pub fn convert_control_code_binary(string: &mut VecDeque, order: bytestream::ByteOrder) -> String{ - - let mut control_code = ControlCode {tag_group:0,tag_type:0,params_size:0,params:Vec::::new()}; +pub fn convert_control_code_binary( + string: &mut VecDeque, + order: bytestream::ByteOrder, +) -> String { + let mut control_code = ControlCode { + tag_group: 0, + tag_type: 0, + params_size: 0, + params: Vec::::new(), + }; //Reading the group of the code let byte_temp = [string.pop_front().unwrap(), string.pop_front().unwrap()]; @@ -37,14 +44,21 @@ pub fn convert_control_code_binary(string: &mut VecDeque, order: bytestream: } match control_code.tag_group { 0 => write_global(control_code), - _ => write_raw_code(control_code) + _ => write_raw_code(control_code), } // Now we write the final string } -pub fn convert_control_code_close_binary(string: &mut VecDeque, order: bytestream::ByteOrder) -> String { - - let mut control_code = ControlCode {tag_group:0,tag_type:0,params_size:0,params:Vec::::new()}; +pub fn convert_control_code_close_binary( + string: &mut VecDeque, + order: bytestream::ByteOrder, +) -> String { + let mut control_code = ControlCode { + tag_group: 0, + tag_type: 0, + params_size: 0, + params: Vec::::new(), + }; //Reading the group of the code let byte_temp = [string.pop_front().unwrap(), string.pop_front().unwrap()]; @@ -55,7 +69,7 @@ pub fn convert_control_code_close_binary(string: &mut VecDeque, order: bytes let byte_temp = [string.pop_front().unwrap(), string.pop_front().unwrap()]; let byte = read_char(byte_temp, order); control_code.tag_type = byte; - + // Now we write the final string let mut control_string = String::from("[/RawCmd "); control_string += &control_code.tag_group.to_string(); @@ -66,7 +80,7 @@ pub fn convert_control_code_close_binary(string: &mut VecDeque, order: bytes control_string } -pub fn convert_control_code(code: &str, order: bytestream::ByteOrder) -> Vec{ +pub fn convert_control_code(code: &str, order: bytestream::ByteOrder) -> Vec { let mut bare_code = code.to_string(); bare_code.remove(0); bare_code.pop(); @@ -79,15 +93,11 @@ pub fn convert_control_code(code: &str, order: bytestream::ByteOrder) -> Vec convert_raw_code(bare_content[1], "", order) } } - "Colour" | "Color" => { - convert_colour_code(bare_content[1], order) - } - "Size" => { - convert_size_code(bare_content[1], order) - } + "Colour" | "Color" => convert_colour_code(bare_content[1], order), + "Size" => convert_size_code(bare_content[1], order), _ => { let mut raw_bytes = Vec::::new(); - for char in code.chars(){ + for char in code.chars() { raw_bytes.append(&mut convert_char(char, order)); } raw_bytes @@ -95,14 +105,14 @@ pub fn convert_control_code(code: &str, order: bytestream::ByteOrder) -> Vec } } -pub fn convert_control_code_close(code: &str, order: bytestream::ByteOrder) -> Vec{ +pub fn convert_control_code_close(code: &str, order: bytestream::ByteOrder) -> Vec { let mut raw_bytes = Vec::::new(); let mut bare_code = code.to_string(); bare_code.remove(0); bare_code.remove(0); bare_code.pop(); let bare_content = bare_code.split(' ').collect::>(); - match bare_content[0]{ + match bare_content[0] { "RawCmd" => { let code_def = bare_content[1].split('.').collect::>(); let tag_group: u16 = code_def[0].parse().unwrap(); @@ -110,19 +120,19 @@ pub fn convert_control_code_close(code: &str, order: bytestream::ByteOrder) -> V raw_bytes.push(0x0F); raw_bytes.push(0x00); - match order{ + match order { ByteOrder::BigEndian => { raw_bytes.append(&mut tag_group.to_be_bytes().to_vec()); raw_bytes.append(&mut tag_type.to_be_bytes().to_vec()); - }, + } ByteOrder::LittleEndian => { raw_bytes.append(&mut tag_group.to_le_bytes().to_vec()); raw_bytes.append(&mut tag_type.to_le_bytes().to_vec()); - }, + } } } - _=> { - for char in code.chars(){ + _ => { + for char in code.chars() { raw_bytes.append(&mut convert_char(char, order)); } } @@ -130,28 +140,28 @@ pub fn convert_control_code_close(code: &str, order: bytestream::ByteOrder) -> V raw_bytes } -fn write_global(code: ControlCode) -> String{ +fn write_global(code: ControlCode) -> String { match code.tag_type { 0 => "[Ruby_to_document]".to_owned(), // Ruby type, string argument? 1 => "[Font_to_document]".to_owned(), // Font type, string argument? - 2 => write_size_code(code), // Text size type. Argument u16? - 3 => write_colour_code(code), // Colour type. Argument #RRGGBBAA - _ => write_raw_code(code).to_owned() //Unknown type. All types are hopefully handled above. + 2 => write_size_code(code), // Text size type. Argument u16? + 3 => write_colour_code(code), // Colour type. Argument #RRGGBBAA + _ => write_raw_code(code).to_owned(), //Unknown type. All types are hopefully handled above. } } -fn write_raw_code(code: ControlCode) -> String{ +fn write_raw_code(code: ControlCode) -> String { let mut control_string = String::from("[RawCmd "); control_string += &code.tag_group.to_string(); control_string += "."; control_string += &code.tag_type.to_string(); - if code.params_size > 0{ + if code.params_size > 0 { control_string += " "; - for code in code.params{ + for code in code.params { control_string += &format!("{code:02X}"); control_string += "_"; } - control_string.truncate(control_string.len()-1); + control_string.truncate(control_string.len() - 1); } control_string += "]"; control_string @@ -159,135 +169,149 @@ fn write_raw_code(code: ControlCode) -> String{ fn write_size_code(code: ControlCode) -> String { let mut control_string = String::from("[Size "); - for code in code.params{ - control_string += &format!("{code:02X}"); - } - control_string.truncate(control_string.len()-1); + for code in code.params { + control_string += &format!("{code:02X}"); + } + control_string.truncate(control_string.len() - 1); control_string += "]"; control_string } fn write_colour_code(code: ControlCode) -> String { let mut control_string = String::from("[Colour #"); - for code in code.params{ - control_string += &format!("{code:02X}"); - } - control_string.truncate(control_string.len()-1); + for code in code.params { + control_string += &format!("{code:02X}"); + } + control_string.truncate(control_string.len() - 1); control_string += "]"; control_string } -fn convert_raw_code(code_type: &str, args: &str, order: bytestream::ByteOrder) -> Vec{ +fn convert_raw_code(code_type: &str, args: &str, order: bytestream::ByteOrder) -> Vec { let mut raw_bytes = Vec::::new(); - let mut control_code = ControlCode{ - tag_group: 0, - tag_type: 0, - params_size: 0, - params: Vec::::new() + let mut control_code = ControlCode { + tag_group: 0, + tag_type: 0, + params_size: 0, + params: Vec::::new(), }; let code_def = code_type.split('.').collect::>(); control_code.tag_group = code_def[0].parse().unwrap(); control_code.tag_type = code_def[1].parse().unwrap(); - if !args.is_empty(){ - control_code.params_size = ((args.len()+1)/3) as u16; + if !args.is_empty() { + control_code.params_size = ((args.len() + 1) / 3) as u16; for byte in args.split('_').collect::>() { - control_code.params.push(u8::from_str_radix(byte, 16).unwrap()); + control_code + .params + .push(u8::from_str_radix(byte, 16).unwrap()); } } else { control_code.params_size = 0u16; } raw_bytes.push(0x0E); raw_bytes.push(0x00); - match order{ + match order { ByteOrder::BigEndian => { raw_bytes.append(&mut control_code.tag_group.to_be_bytes().to_vec()); raw_bytes.append(&mut control_code.tag_type.to_be_bytes().to_vec()); raw_bytes.append(&mut control_code.params_size.to_be_bytes().to_vec()); - }, + } ByteOrder::LittleEndian => { raw_bytes.append(&mut control_code.tag_group.to_le_bytes().to_vec()); raw_bytes.append(&mut control_code.tag_type.to_le_bytes().to_vec()); raw_bytes.append(&mut control_code.params_size.to_le_bytes().to_vec()); - }, + } } - if control_code.params_size != 0{ + if control_code.params_size != 0 { raw_bytes.append(&mut control_code.params); } raw_bytes } -fn convert_colour_code(args: &str, order: bytestream::ByteOrder) -> Vec{ +fn convert_colour_code(args: &str, order: bytestream::ByteOrder) -> Vec { let mut raw_bytes = Vec::::new(); let mut bare_args = args.to_string(); bare_args.remove(0); - let mut control_code = ControlCode{ - tag_group: 0, - tag_type: 3, - params_size: 4, - params: Vec::::new() + let mut control_code = ControlCode { + tag_group: 0, + tag_type: 3, + params_size: 4, + params: Vec::::new(), }; - for _i in 0..bare_args.len()/2{ - let arg:String = args.chars().skip(control_code.params.len()*2).take(2).collect(); - control_code.params.push(u8::from_str_radix(&arg, 16).unwrap()) - } + for _i in 0..bare_args.len() / 2 { + let arg: String = args + .chars() + .skip(control_code.params.len() * 2) + .take(2) + .collect(); + control_code + .params + .push(u8::from_str_radix(&arg, 16).unwrap()) + } raw_bytes.push(0x0E); raw_bytes.push(0x00); - match order{ + match order { ByteOrder::BigEndian => { raw_bytes.append(&mut control_code.tag_group.to_be_bytes().to_vec()); raw_bytes.append(&mut control_code.tag_type.to_be_bytes().to_vec()); raw_bytes.append(&mut control_code.params_size.to_be_bytes().to_vec()); - }, + } ByteOrder::LittleEndian => { raw_bytes.append(&mut control_code.tag_group.to_le_bytes().to_vec()); raw_bytes.append(&mut control_code.tag_type.to_le_bytes().to_vec()); raw_bytes.append(&mut control_code.params_size.to_le_bytes().to_vec()); - }, + } } - if control_code.params_size != 0{ + if control_code.params_size != 0 { raw_bytes.append(&mut control_code.params); } raw_bytes } -fn convert_size_code(args: &str, order: bytestream::ByteOrder) -> Vec{ +fn convert_size_code(args: &str, order: bytestream::ByteOrder) -> Vec { let mut raw_bytes = Vec::::new(); let mut bare_args = args.to_string(); bare_args.remove(0); - let mut control_code = ControlCode{ - tag_group: 0, - tag_type: 2, - params_size: 2, - params: Vec::::new() + let mut control_code = ControlCode { + tag_group: 0, + tag_type: 2, + params_size: 2, + params: Vec::::new(), }; - for _i in 0..bare_args.len()/2{ - let arg:String = args.chars().skip(control_code.params.len()*2).take(2).collect(); - control_code.params.push(u8::from_str_radix(&arg, 16).unwrap()) - } + for _i in 0..bare_args.len() / 2 { + let arg: String = args + .chars() + .skip(control_code.params.len() * 2) + .take(2) + .collect(); + control_code + .params + .push(u8::from_str_radix(&arg, 16).unwrap()) + } raw_bytes.push(0x0E); raw_bytes.push(0x00); - match order{ + match order { ByteOrder::BigEndian => { raw_bytes.append(&mut control_code.tag_group.to_be_bytes().to_vec()); raw_bytes.append(&mut control_code.tag_type.to_be_bytes().to_vec()); raw_bytes.append(&mut control_code.params_size.to_be_bytes().to_vec()); - }, + } ByteOrder::LittleEndian => { raw_bytes.append(&mut control_code.tag_group.to_le_bytes().to_vec()); raw_bytes.append(&mut control_code.tag_type.to_le_bytes().to_vec()); raw_bytes.append(&mut control_code.params_size.to_le_bytes().to_vec()); - }, + } } - if control_code.params_size != 0{ + if control_code.params_size != 0 { raw_bytes.append(&mut control_code.params); } raw_bytes -} \ No newline at end of file +} diff --git a/src/diff_utils.rs b/src/diff_utils.rs index 5d37022..22fe707 100644 --- a/src/diff_utils.rs +++ b/src/diff_utils.rs @@ -1,28 +1,31 @@ -use std::{fs::File, io::{BufReader, Lines}}; +use std::{ + fs::File, + io::{BufReader, Lines}, +}; use crate::msbt::MSBTString; #[derive(Debug, Clone)] -pub struct StringDiff{ +pub struct StringDiff { state: State, label: String, - string: String + string: String, } #[derive(Debug, Clone, PartialEq)] -pub enum State{ +pub enum State { Added, Deleted, Edited, - Null + Null, } pub fn get_added(original: Vec, vec_edited: Vec>) -> Vec { let mut result = Vec::::new(); - for edited in vec_edited{ + for edited in vec_edited { for string in edited { let index = original.iter().position(|s| s.label == string.label); - if index.is_none(){ + if index.is_none() { result.push(string); } } @@ -32,10 +35,10 @@ pub fn get_added(original: Vec, vec_edited: Vec>) -> pub fn get_deleted(original: Vec, vec_edited: Vec>) -> Vec { let mut result = Vec::::new(); - for edited in vec_edited{ + for edited in vec_edited { for string in &original { let index = edited.iter().position(|s| s.label == string.label); - if index.is_none(){ + if index.is_none() { result.push(string.to_owned()); } } @@ -45,12 +48,12 @@ pub fn get_deleted(original: Vec, vec_edited: Vec>) pub fn get_edited(original: Vec, vec_edited: Vec>) -> Vec { let mut result = Vec::::new(); - for edited in vec_edited{ + for edited in vec_edited { for string in edited { let index = original.iter().position(|s| s.label == string.label); - if index.is_some(){ + if index.is_some() { let string_original = original.get(index.unwrap()).unwrap(); - if string_original.string != string.string{ + if string_original.string != string.string { result.push(string); } } @@ -61,30 +64,38 @@ pub fn get_edited(original: Vec, vec_edited: Vec>) - pub fn convert_diff(diff: Lines>) -> ::msbt::Result> { let mut result = Vec::::new(); - let mut current_diff = StringDiff { state: State::Null, label: "".to_owned(), string: "".to_owned() }; + let mut current_diff = StringDiff { + state: State::Null, + label: "".to_owned(), + string: "".to_owned(), + }; for line in diff.map_while(Result::ok) { if line.is_empty() { - if current_diff.state != State::Null{ + if current_diff.state != State::Null { current_diff.string = current_diff.string.trim().to_owned(); result.push(current_diff.clone()); - current_diff = StringDiff { state: State::Null, label: "".to_owned(), string: "".to_owned() }; + current_diff = StringDiff { + state: State::Null, + label: "".to_owned(), + string: "".to_owned(), + }; } } else if current_diff.state == State::Null { - let mut chars: Vec = line.chars().collect(); - match *chars.first().unwrap(){ - '+' => current_diff.state = State::Added, - '-' => current_diff.state = State::Deleted, - '~' => current_diff.state = State::Edited, - _ => return Err(::msbt::Error::MalformedDiffUnrecognizedState) - } - chars.remove(0); - current_diff.label = chars.into_iter().collect(); - println!("Found edit {}!", current_diff.label) - } else { - let mut edited_line = line.clone(); - edited_line.remove(0); - edited_line.push('\n'); - current_diff.string.push_str(&edited_line); + let mut chars: Vec = line.chars().collect(); + match *chars.first().unwrap() { + '+' => current_diff.state = State::Added, + '-' => current_diff.state = State::Deleted, + '~' => current_diff.state = State::Edited, + _ => return Err(::msbt::Error::MalformedDiffUnrecognizedState), + } + chars.remove(0); + current_diff.label = chars.into_iter().collect(); + println!("Found edit {}!", current_diff.label) + } else { + let mut edited_line = line.clone(); + edited_line.remove(0); + edited_line.push('\n'); + current_diff.string.push_str(&edited_line); } } current_diff.string = current_diff.string.trim().to_owned(); @@ -92,17 +103,30 @@ pub fn convert_diff(diff: Lines>) -> ::msbt::Result, msbt: Vec, order: bytestream::ByteOrder) -> ::msbt::Result>{ +pub fn patch_diff( + diff: Vec, + msbt: Vec, + order: bytestream::ByteOrder, +) -> ::msbt::Result> { let mut new_msbt = msbt.clone(); for string_diff in diff { println!("Patching {}...", string_diff.label); let corrected_string = string_diff.string + "\0"; match string_diff.state { - State::Added => ::msbt::msbt::add_string(&mut new_msbt, string_diff.label, corrected_string, order), - State::Deleted => ::msbt::msbt::delete_string_by_label(&mut new_msbt, string_diff.label), - State::Edited => ::msbt::msbt::edit_string_by_label(&mut new_msbt, string_diff.label, corrected_string, order), - State::Null => {}, + State::Added => { + ::msbt::msbt::add_string(&mut new_msbt, string_diff.label, corrected_string, order) + } + State::Deleted => { + ::msbt::msbt::delete_string_by_label(&mut new_msbt, string_diff.label) + } + State::Edited => ::msbt::msbt::edit_string_by_label( + &mut new_msbt, + string_diff.label, + corrected_string, + order, + ), + State::Null => {} } } Ok(new_msbt) -} \ No newline at end of file +} diff --git a/src/error.rs b/src/error.rs index 8e8b4d5..7dc3710 100644 --- a/src/error.rs +++ b/src/error.rs @@ -4,7 +4,6 @@ pub type Result = std::result::Result; #[derive(Error, Debug)] pub enum Error { - /// Error passed from std::io #[error("System error: {0}")] IOError(std::io::Error), @@ -32,10 +31,9 @@ pub enum Error { #[error("The hashes of the MSBT file and the diff file don't match!")] BadHash, - /// Error called when an error happens when reading a + /// Error called when an error happens when reading a #[error("Unrecognized state for a string! States should be '+' (added), '-' (deleted) or '~' (edited)!")] MalformedDiffUnrecognizedState, - } impl From for Error { @@ -54,4 +52,4 @@ impl From for Error { fn from(err: toml::de::Error) -> Self { Self::MalformedToml(err) } -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index 5e72315..dd03abb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ -pub mod structs; +pub mod control_codes; pub mod error; pub mod msbt; -pub mod control_codes; +pub mod structs; -pub use error::{Error, Result}; \ No newline at end of file +pub use error::{Error, Result}; diff --git a/src/main.rs b/src/main.rs index 2d9c0b2..d3dc77c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,9 +3,9 @@ use std::fs::{self, File}; use std::io::{self, BufRead, Read, Write}; use std::path::Path; -use diff_utils::convert_diff; use ::msbt::msbt::MSBTString; use clap::{Parser, ValueEnum}; +use diff_utils::convert_diff; use msbt::msbt; use serde::{Deserialize, Serialize}; @@ -71,7 +71,7 @@ fn extract_msbt(args: Args) -> ::msbt::Result<()> { for string in strings { let mut parsed_string = ::msbt::structs::TXT2::parse_binary(string.string, msbt.endianness); - if parsed_string.ends_with('\0'){ + if parsed_string.ends_with('\0') { parsed_string.truncate(parsed_string.len() - 1); } output_map.insert(string.label, parsed_string); @@ -86,9 +86,16 @@ fn extract_msbt(args: Args) -> ::msbt::Result<()> { strings: output_map, }; let serialized = toml::ser::to_string_pretty(&msbt_json).unwrap(); - - - let output_path = if args.output.is_some(){args.output.unwrap()} else {filepath.join(filename.to_owned() + ".toml").into_os_string().into_string().unwrap()}; + + let output_path = if args.output.is_some() { + args.output.unwrap() + } else { + filepath + .join(filename.to_owned() + ".toml") + .into_os_string() + .into_string() + .unwrap() + }; let mut result = File::create(output_path)?; result.write_all(serialized.as_bytes())?; Ok(()) @@ -106,12 +113,24 @@ fn create_msbt_args(args: Args) -> ::msbt::Result<()> { let toml = get_toml(file)?; let strings = get_strings_toml(&toml)?; let order = get_endianness_toml(&toml)?; - let output_path = if args.output.is_some(){args.output.unwrap()} else {filepath.join(filename.to_owned() + ".msbt").into_os_string().into_string().unwrap()}; - let _ = create_msbt(output_path, strings, order); + let output_path = if args.output.is_some() { + args.output.unwrap() + } else { + filepath + .join(filename.to_owned() + ".msbt") + .into_os_string() + .into_string() + .unwrap() + }; + create_msbt(output_path, strings, order)?; Ok(()) } -fn create_msbt(filename: String, msbt: Vec, order: bytestream::ByteOrder) -> ::msbt::Result<()>{ +fn create_msbt( + filename: String, + msbt: Vec, + order: bytestream::ByteOrder, +) -> ::msbt::Result<()> { let new_msbt = msbt::to_binary(msbt, order)?; let mut result = File::create(filename)?; result.write_all(&new_msbt)?; @@ -140,7 +159,8 @@ fn diff_msbt(args: Args) -> ::msbt::Result<()> { let msbt = msbt::from_binary(&mut file)?; endianness = msbt.endianness; orig_strings = msbt::get_strings(msbt.clone())?; - } else { //Just assume it's toml + } else { + //Just assume it's toml let file = File::open(args.original)?; let toml = get_toml(file)?; endianness = get_endianness_toml(&toml)?; @@ -158,7 +178,8 @@ fn diff_msbt(args: Args) -> ::msbt::Result<()> { let mut file = File::open(path_edited)?; let msbt = msbt::from_binary(&mut file)?; msbt::get_strings(msbt.clone())? - } else { //Just assume it's toml + } else { + //Just assume it's toml let file = File::open(path_edited)?; let toml = get_toml(file)?; get_strings_toml(&toml)? @@ -169,59 +190,67 @@ fn diff_msbt(args: Args) -> ::msbt::Result<()> { let deleted_strings = diff_utils::get_deleted(orig_strings.clone(), edited_strings.clone()); let edited_strings = diff_utils::get_edited(orig_strings, edited_strings); - - if !added_strings.is_empty() || !deleted_strings.is_empty() || !edited_strings.is_empty(){ - let output_path = if args.output.is_some(){args.output.unwrap()} else {filepath.join(filename.to_owned() + ".msbd.txt").into_os_string().into_string().unwrap()}; + if !added_strings.is_empty() || !deleted_strings.is_empty() || !edited_strings.is_empty() { + let output_path = if args.output.is_some() { + args.output.unwrap() + } else { + filepath + .join(filename.to_owned() + ".msbd.txt") + .into_os_string() + .into_string() + .unwrap() + }; let mut diff_file = File::create(output_path)?; //Writing file - let _ = diff_file.write((filename.to_owned()+"\n").as_bytes()); - let _ = diff_file.write((filename.to_owned()+"\n").as_bytes()); - if !hash.is_empty(){ - let _ = diff_file.write((hash+"\n").as_bytes()); + diff_file.write_all((filename.to_owned() + "\n").as_bytes())?; + diff_file.write_all((filename.to_owned() + "\n").as_bytes())?; + if !hash.is_empty() { + diff_file.write_all((hash + "\n").as_bytes())?; } - let _ = diff_file.write("\n".as_bytes()); + diff_file.write_all("\n".as_bytes())?; //Writing added strings... - for string in added_strings{ - let label = "+".to_owned()+&string.label+"\n"; - let _ = diff_file.write(label.as_bytes()); + for string in added_strings { + let label = "+".to_owned() + &string.label + "\n"; + diff_file.write_all(label.as_bytes())?; let mut parsed_string = ::msbt::structs::TXT2::parse_binary(string.string, endianness); - if parsed_string.ends_with('\0'){ + if parsed_string.ends_with('\0') { parsed_string.truncate(parsed_string.len() - 1); } parsed_string = parsed_string.replace('\n', "\n>"); - let _ = diff_file.write((">".to_owned()+&parsed_string+"\n").as_bytes()); - let _ = diff_file.write("\n".as_bytes()); + diff_file.write_all((">".to_owned() + &parsed_string + "\n").as_bytes())?; + diff_file.write_all("\n".as_bytes())?; } //Writing deleted strings... - for string in deleted_strings{ - let label = "-".to_owned()+&string.label+"\n"; - let _ = diff_file.write(label.as_bytes()); - let _ = diff_file.write("\n".as_bytes()); + for string in deleted_strings { + let label = "-".to_owned() + &string.label + "\n"; + diff_file.write_all(label.as_bytes())?; + diff_file.write_all("\n".as_bytes())?; } //Writing edits... - for string in edited_strings{ - let label = "~".to_owned()+&string.label+"\n"; - let _ = diff_file.write(label.as_bytes()); + for string in edited_strings { + let label = "~".to_owned() + &string.label + "\n"; + diff_file.write_all(label.as_bytes())?; let mut parsed_string = ::msbt::structs::TXT2::parse_binary(string.string, endianness); - if parsed_string.ends_with('\0'){ + if parsed_string.ends_with('\0') { parsed_string.truncate(parsed_string.len() - 1); } parsed_string = parsed_string.replace('\n', "\n>"); - let _ = diff_file.write((">".to_owned()+&parsed_string+"\n").as_bytes()); - let _ = diff_file.write("\n".as_bytes()); + diff_file.write_all((">".to_owned() + &parsed_string + "\n").as_bytes())?; + diff_file.write_all("\n".as_bytes())?; } } Ok(()) } fn patch_msbt(args: Args) -> ::msbt::Result<()> { + // BUG: only one patch + // PANIC: when no patch files are given let diff_file = File::open(args.edited.first().unwrap())?; let mut lines = io::BufReader::new(diff_file).lines(); - let _final_filename = lines.next().unwrap()?; let patch_name = lines.next().unwrap()?; let sha256 = lines.next().unwrap()?; if !sha256.is_empty() { @@ -237,28 +266,35 @@ fn patch_msbt(args: Args) -> ::msbt::Result<()> { let path = Path::new(&arg_filename); let extension = path.extension().unwrap().to_str().unwrap().to_lowercase(); if extension == "msbt" { - let _filename = path.file_stem().unwrap().to_str().unwrap(); let filepath = path.parent().unwrap(); let mut file = File::open(args.original)?; let msbt = msbt::from_binary(&mut file)?; let strings = msbt::get_strings(msbt.clone())?; - + let diff = convert_diff(lines).unwrap(); let new_msbt = diff_utils::patch_diff(diff, strings, msbt.endianness)?; - let output_path = if args.output.is_some(){args.output.unwrap()} else {filepath.join(patch_name.to_owned() + ".msbt").into_os_string().into_string().unwrap()}; - match create_msbt(output_path, new_msbt, msbt.endianness){ - Ok(_) => {}, + let output_path = if args.output.is_some() { + args.output.unwrap() + } else { + filepath + .join(patch_name.to_owned() + ".msbt") + .into_os_string() + .into_string() + .unwrap() + }; + match create_msbt(output_path, new_msbt, msbt.endianness) { + Ok(_) => {} Err(_) => panic!("Error writing MSBT file."), }; } Ok(()) } -fn get_toml(mut file: File) -> ::msbt::Result{ +fn get_toml(mut file: File) -> ::msbt::Result { let mut toml_string = "".to_owned(); - let _ = file.read_to_string(&mut toml_string); + file.read_to_string(&mut toml_string)?; Ok(toml::de::from_str(toml_string.as_str())?) } @@ -269,7 +305,7 @@ fn get_endianness_toml(toml: &SerMsbt) -> ::msbt::Result } } -fn get_strings_toml(toml: &SerMsbt) -> ::msbt::Result>{ +fn get_strings_toml(toml: &SerMsbt) -> ::msbt::Result> { let mut strings = Vec::::new(); let order = match toml.is_big_endian { true => bytestream::ByteOrder::BigEndian, diff --git a/src/msbt.rs b/src/msbt.rs index 4d1426b..254e3fa 100644 --- a/src/msbt.rs +++ b/src/msbt.rs @@ -2,30 +2,33 @@ use std::io::{Read, Seek}; use bytestream::ByteOrder; -use crate::structs::{Header, ATR1, LBL1, TXT2}; use crate::error::Result; - +use crate::structs::{Header, ATR1, LBL1, TXT2}; #[derive(Clone)] -pub struct MSBT{ +pub struct MSBT { _header: Header, lbl1: LBL1, _atr1: ATR1, txt2: TXT2, pub endianness: bytestream::ByteOrder, - pub has_attributes: bool + pub has_attributes: bool, } #[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd)] pub struct MSBTString { pub index: u32, pub label: String, - pub string: Vec + pub string: Vec, } -pub fn from_binary(buffer: &mut R) -> Result { +pub fn from_binary(buffer: &mut R) -> Result { let header = Header::read_from(buffer)?; - let byte_order = if header.endianness {ByteOrder::BigEndian} else {ByteOrder::LittleEndian}; + let byte_order = if header.endianness { + ByteOrder::BigEndian + } else { + ByteOrder::LittleEndian + }; let lbl1 = LBL1::read_from(buffer, byte_order)?; let atr1 = ATR1::read_from(buffer, byte_order)?; let mut has_attributes = true; @@ -33,21 +36,20 @@ pub fn from_binary(buffer: &mut R) -> Result { has_attributes = false; } let txt2 = TXT2::read_from(buffer, byte_order)?; - Ok(MSBT { + Ok(MSBT { _header: header, lbl1, _atr1: atr1, txt2, endianness: byte_order, - has_attributes - } - ) + has_attributes, + }) } pub fn get_strings(msbt: MSBT) -> Result> { let mut msbt_strings = Vec::::new(); - for label in msbt.lbl1.labels{ - let string = MSBTString{ + for label in msbt.lbl1.labels { + let string = MSBTString { index: label.string_index, label: label.label, string: msbt.txt2.strings[(label.string_index) as usize].clone(), @@ -59,38 +61,49 @@ pub fn get_strings(msbt: MSBT) -> Result> { pub fn add_string_raw(msbt_strings: &mut Vec, label: String, string: Vec) { let last = msbt_strings.iter().map(|c| c.index).max().unwrap(); - let new_string = MSBTString{ - index: last+1, + let new_string = MSBTString { + index: last + 1, label, - string + string, }; msbt_strings.push(new_string); } -pub fn add_string(msbt_strings: &mut Vec, label: String, string: String, order: bytestream::ByteOrder) { +pub fn add_string( + msbt_strings: &mut Vec, + label: String, + string: String, + order: bytestream::ByteOrder, +) { let last = msbt_strings.iter().map(|c| c.index).max().unwrap(); let new_string: Vec = match order { - ByteOrder::BigEndian => string.encode_utf16().flat_map(|c| c.to_be_bytes()).collect(), - ByteOrder::LittleEndian => string.encode_utf16().flat_map(|c| c.to_le_bytes()).collect(), + ByteOrder::BigEndian => string + .encode_utf16() + .flat_map(|c| c.to_be_bytes()) + .collect(), + ByteOrder::LittleEndian => string + .encode_utf16() + .flat_map(|c| c.to_le_bytes()) + .collect(), }; - let new_msbt_string = MSBTString{ - index: last+1, + let new_msbt_string = MSBTString { + index: last + 1, label, - string: new_string + string: new_string, }; msbt_strings.push(new_msbt_string); } -pub fn delete_string_by_index(msbt_strings: &mut Vec,index: u32){ +pub fn delete_string_by_index(msbt_strings: &mut Vec, index: u32) { let vec_index = msbt_strings.iter().position(|s| s.index == index).unwrap(); delete_string(msbt_strings, vec_index); } -pub fn delete_string_by_label(msbt_strings: &mut Vec,label: String){ +pub fn delete_string_by_label(msbt_strings: &mut Vec, label: String) { let vec_index = msbt_strings.iter().position(|s| s.label == label).unwrap(); delete_string(msbt_strings, vec_index); } -fn delete_string(msbt_strings: &mut Vec,vec_index: usize){ +fn delete_string(msbt_strings: &mut Vec, vec_index: usize) { let msbt_index = msbt_strings[vec_index].index; msbt_strings.remove(vec_index); for string in msbt_strings { @@ -100,35 +113,53 @@ fn delete_string(msbt_strings: &mut Vec,vec_index: usize){ } } -pub fn edit_string_by_label(msbt_strings: &mut [MSBTString],label: String, string: String, order: bytestream::ByteOrder){ +pub fn edit_string_by_label( + msbt_strings: &mut [MSBTString], + label: String, + string: String, + order: bytestream::ByteOrder, +) { let new_string: Vec = match order { - ByteOrder::BigEndian => string.encode_utf16().flat_map(|c| c.to_be_bytes()).collect(), - ByteOrder::LittleEndian => string.encode_utf16().flat_map(|c| c.to_le_bytes()).collect(), + ByteOrder::BigEndian => string + .encode_utf16() + .flat_map(|c| c.to_be_bytes()) + .collect(), + ByteOrder::LittleEndian => string + .encode_utf16() + .flat_map(|c| c.to_le_bytes()) + .collect(), }; - match msbt_strings.iter().position(|s| s.label == label){ + match msbt_strings.iter().position(|s| s.label == label) { Some(index) => { let old_index = msbt_strings.get(index).unwrap().index; - msbt_strings[index] = MSBTString{ index: old_index, label, string:new_string }; - }, + msbt_strings[index] = MSBTString { + index: old_index, + label, + string: new_string, + }; + } None => println!("No label named \"{}\" found!", label), }; } - -pub fn to_binary(msbt_strings: Vec, order: bytestream::ByteOrder) -> Result>{ - println!("Formatting {} strings to MSBT, {} endian", msbt_strings.len(), match order{ - ByteOrder::BigEndian => "big", - ByteOrder::LittleEndian => "little", - }); - let mut file= Vec::::new(); +pub fn to_binary(msbt_strings: Vec, order: bytestream::ByteOrder) -> Result> { + println!( + "Formatting {} strings to MSBT, {} endian", + msbt_strings.len(), + match order { + ByteOrder::BigEndian => "big", + ByteOrder::LittleEndian => "little", + } + ); + let mut file = Vec::::new(); let mut lbl1 = LBL1::write_binary(msbt_strings.clone(), order)?; let mut atr1 = ATR1::write_binary(msbt_strings.clone(), order)?; let mut txt2 = TXT2::write_binary(msbt_strings.clone(), order)?; - let mut header = Header::write_binary(3, (lbl1.len()+atr1.len()+txt2.len()) as u32, order)?; + let mut header = Header::write_binary(3, (lbl1.len() + atr1.len() + txt2.len()) as u32, order)?; file.append(&mut header); file.append(&mut lbl1); file.append(&mut atr1); file.append(&mut txt2); println!("Formatted MSBT."); Ok(file) -} \ No newline at end of file +} diff --git a/src/structs.rs b/src/structs.rs index 72e09bf..bda3592 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -1,9 +1,9 @@ +pub mod atr1; pub mod header; pub mod lbl1; -pub mod atr1; pub mod txt2; +pub use atr1::ATR1; pub use header::Header; pub use lbl1::LBL1; -pub use atr1::ATR1; pub use txt2::TXT2; diff --git a/src/structs/atr1.rs b/src/structs/atr1.rs index ba30735..a64bf4d 100644 --- a/src/structs/atr1.rs +++ b/src/structs/atr1.rs @@ -5,36 +5,46 @@ use crate::msbt::MSBTString; use bytestream::{ByteOrder, StreamReader}; #[derive(Debug, Clone)] -pub struct ATR1{ // Not enough data, since only Rhythm Heaven Megamix has been used for research. +pub struct ATR1 { + // Not enough data, since only Rhythm Heaven Megamix has been used for research. _magic: Vec, pub section_size: u32, - pub string_amount:u64 + pub string_amount: u64, } -impl ATR1{ +impl ATR1 { pub fn read_from(buffer: &mut R, order: bytestream::ByteOrder) -> Result { println!("Extracting attributes..."); let block_start = buffer.stream_position()?; - let mut magic = vec![0u8;4]; + let mut magic = vec![0u8; 4]; buffer.read_exact(&mut magic)?; if magic != b"ATR1" { buffer.seek(SeekFrom::Current(-4))?; println!("No ATR1 section, continuing..."); - return Ok(ATR1{ _magic: "NONE".as_bytes().to_vec(), section_size: 0, string_amount: 0 }); + return Ok(ATR1 { + _magic: "NONE".as_bytes().to_vec(), + section_size: 0, + string_amount: 0, + }); } let section_size = u32::read_from(buffer, order)?; buffer.seek(SeekFrom::Current(8))?; let string_amount = u64::read_from(buffer, order)?; - buffer.seek(SeekFrom::Start(block_start+0x10+section_size as u64+(0x10-(section_size%0x10)) as u64))?; + buffer.seek(SeekFrom::Start( + block_start + 0x10 + section_size as u64 + (0x10 - (section_size % 0x10)) as u64, + ))?; println!("Extracted attributes."); - Ok(ATR1 { + Ok(ATR1 { _magic: magic, section_size, - string_amount + string_amount, }) } - pub fn write_binary(msbt_strings: Vec, order: bytestream::ByteOrder) -> Result>{ + pub fn write_binary( + msbt_strings: Vec, + order: bytestream::ByteOrder, + ) -> Result> { println!("Formatting attributes..."); let mut result = Vec::::new(); let section_size = 8_u32; @@ -43,21 +53,21 @@ impl ATR1{ match order { ByteOrder::BigEndian => { result.append(&mut section_size.to_be_bytes().to_vec()); - result.append(&mut vec![0,0,0,0,0,0,0,0]); + result.append(&mut vec![0, 0, 0, 0, 0, 0, 0, 0]); result.append(&mut (msbt_strings.len()).to_be_bytes().to_vec()); } ByteOrder::LittleEndian => { result.append(&mut section_size.to_le_bytes().to_vec()); - result.append(&mut vec![0,0,0,0,0,0,0,0]); + result.append(&mut vec![0, 0, 0, 0, 0, 0, 0, 0]); result.append(&mut (msbt_strings.len()).to_le_bytes().to_vec()); } } - let padding = 16 - result.len() %16; - for _i in 0..padding{ + let padding = 16 - result.len() % 16; + for _i in 0..padding { result.push(0xD0); } println!("Formated attributes."); Ok(result) } -} \ No newline at end of file +} diff --git a/src/structs/header.rs b/src/structs/header.rs index ff53407..fab417f 100644 --- a/src/structs/header.rs +++ b/src/structs/header.rs @@ -1,31 +1,31 @@ -use std::io::{Read, Seek, SeekFrom}; -use bytestream::{ByteOrder, StreamReader}; use crate::error::{Error, Result}; +use bytestream::{ByteOrder, StreamReader}; +use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone)] -pub struct Header{ +pub struct Header { _magic: Vec, pub endianness: bool, - _unk1: u16, // ??? Always 0 + _unk1: u16, // ??? Always 0 _encoding: u8, // Message encoding (0=UTF-8, 1=UTF-16, 2=UTF-32) - _version: u8, // Version? Always 03 + _version: u8, // Version? Always 03 pub section_amount: u16, _unk3: u16, _filesize: u32, } -impl Header{ - pub fn read_from(buffer: &mut R) -> Result
{ +impl Header { + pub fn read_from(buffer: &mut R) -> Result
{ println!("Extracting header..."); - let mut magic = vec![0u8;8]; + let mut magic = vec![0u8; 8]; buffer.read_exact(&mut magic)?; if magic != b"MsgStdBn" { - return Err(Error::NotMSBT) + return Err(Error::NotMSBT); } let endianness_raw = u16::read_from(buffer, bytestream::ByteOrder::BigEndian)?; let endianness; let endianness_bool; - if endianness_raw == 0xFEFF{ + if endianness_raw == 0xFEFF { endianness = bytestream::ByteOrder::BigEndian; endianness_bool = true; } else { @@ -34,7 +34,7 @@ impl Header{ } buffer.seek(SeekFrom::Current(10))?; println!("Extracted header."); - Ok(Header{ + Ok(Header { _magic: magic, endianness: endianness_bool, _unk1: u16::read_from(buffer, endianness)?, @@ -46,7 +46,11 @@ impl Header{ }) } - pub fn write_binary(section_amount: u16,section_sizes: u32, order: bytestream::ByteOrder) -> Result>{ + pub fn write_binary( + section_amount: u16, + section_sizes: u32, + order: bytestream::ByteOrder, + ) -> Result> { println!("Formatting header..."); let mut result = Vec::::new(); //binary tiem @@ -54,24 +58,24 @@ impl Header{ match order { ByteOrder::BigEndian => { result.append(&mut vec![0xFE, 0xFF]); - result.append(&mut vec![0,0,1,3]); + result.append(&mut vec![0, 0, 1, 3]); result.append(&mut section_amount.to_be_bytes().to_vec()); - result.append(&mut vec![0,0]); - result.append(&mut (section_sizes+0x20).to_be_bytes().to_vec()); + result.append(&mut vec![0, 0]); + result.append(&mut (section_sizes + 0x20).to_be_bytes().to_vec()); } ByteOrder::LittleEndian => { result.append(&mut vec![0xFF, 0xFE]); - result.append(&mut vec![0,0,1,3]); + result.append(&mut vec![0, 0, 1, 3]); result.append(&mut section_amount.to_le_bytes().to_vec()); - result.append(&mut vec![0,0]); - result.append(&mut (section_sizes+0x20).to_le_bytes().to_vec()); + result.append(&mut vec![0, 0]); + result.append(&mut (section_sizes + 0x20).to_le_bytes().to_vec()); } } - let padding = 16 - result.len() %16; - for _i in 0..padding{ + let padding = 16 - result.len() % 16; + for _i in 0..padding { result.push(0x0); } println!("Formated header."); Ok(result) } -} \ No newline at end of file +} diff --git a/src/structs/lbl1.rs b/src/structs/lbl1.rs index 6957b02..3f913e3 100644 --- a/src/structs/lbl1.rs +++ b/src/structs/lbl1.rs @@ -1,38 +1,41 @@ -use std::io::{Read, Seek, SeekFrom}; +use crate::{ + error::{Error, Result}, + msbt::MSBTString, +}; use bytestream::{ByteOrder, StreamReader}; -use crate::{error::{Error, Result}, msbt::MSBTString}; +use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone)] -pub struct LBL1{ - _magic: Vec::, +pub struct LBL1 { + _magic: Vec, _section_size: u32, _block_amount: u32, pub offsets: Vec, - pub labels: Vec