Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ refactor(lib): Entities have been moved to a separate module #7

Merged
merged 1 commit into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions bytesto4t/src-tauri/src/entities/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use hlbc::Bytecode;
use serde::{Deserialize, Serialize};
use std::sync::Mutex;

#[derive(Serialize, Deserialize)]
pub(crate) struct AppConfig {
pub(crate) file_path: String,
pub(crate) theme: Option<String>,
pub(crate) colorscheme: Option<String>,
pub(crate) recent_files: Option<Vec<String>>,
}

pub(crate) struct AppData {
pub(crate) target_file_path: String,
pub(crate) bytecode: Option<Bytecode>,
pub(crate) app_config: AppConfig,
}

pub(crate) struct Storage {
pub(crate) app_data: Mutex<AppData>,
}
183 changes: 113 additions & 70 deletions bytesto4t/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,16 @@
mod entities;

use crate::entities::{AppConfig, AppData, Storage};
use hlbc::fmt::EnhancedFmt;
use hlbc::types::Type;
use hlbc::Bytecode;
use hlbc::Resolve;
use hlbc_decompiler::{decompile_class, decompile_function};
use std::io::Write;
use std::path::Path;
use std::sync::Mutex;
use serde::{Deserialize, Serialize};
use hlbc::Bytecode;
use hlbc::Resolve;
use hlbc::fmt::EnhancedFmt;
use hlbc::types::Type;
use hlbc_decompiler::{decompile_function, decompile_class};
use tauri::State;
use tauri::Manager;

#[derive(Serialize, Deserialize)]
struct AppConfig {
file_path: String,
theme: Option<String>,
colorscheme: Option<String>,
recent_files: Option<Vec<String>>,
}

struct AppData {
target_file_path: String,
bytecode: Option<Bytecode>,
app_config: AppConfig,
}

struct Storage {
app_data: Mutex<AppData>,
}
use tauri::State;

#[tauri::command]
fn set_target_file_path(file_path: &str, app_data: State<Storage>) -> Result<(), String> {
Expand All @@ -47,8 +31,12 @@ fn get_function_list(app_data: State<Storage>) -> Result<Vec<String>, String> {
let mut function_names = Vec::new();
let mut index = 0;
for function in functions {
function_names.push(function.name(&bytecode).to_string() + &function.findex.to_string() +
"@" + &index.to_string());
function_names.push(
function.name(bytecode).to_string()
+ &function.findex.to_string()
+ "@"
+ &index.to_string(),
);
index += 1;
}

Expand Down Expand Up @@ -81,8 +69,7 @@ fn get_type_list(app_data: State<Storage>) -> Result<Vec<String>, String> {
let mut type_names = Vec::new();
let mut index = 0;
for t in types {
type_names.push(t.display::<EnhancedFmt>(&bytecode).to_string() +
"@" + &index.to_string());
type_names.push(t.display::<EnhancedFmt>(bytecode).to_string() + "@" + &index.to_string());
index += 1;
}

Expand Down Expand Up @@ -112,8 +99,8 @@ fn get_global_list(app_data: State<Storage>) -> Result<Vec<String>, String> {
let mut global_list = Vec::new();
let mut index = 0;
for g in globals {
global_list.push(g.display::<EnhancedFmt>(&bytecode).to_string() +
"@" + &index.to_string());
global_list
.push(g.display::<EnhancedFmt>(bytecode).to_string() + "@" + &index.to_string());
index += 1;
}

Expand All @@ -128,8 +115,8 @@ fn get_native_list(app_data: State<Storage>) -> Result<Vec<String>, String> {
let mut native_list = Vec::new();
let mut index = 0;
for n in natives {
native_list.push(n.display::<EnhancedFmt>(&bytecode).to_string() +
"@" + &index.to_string());
native_list
.push(n.display::<EnhancedFmt>(bytecode).to_string() + "@" + &index.to_string());
index += 1;
}

Expand Down Expand Up @@ -184,7 +171,6 @@ fn get_float_list(app_data: State<Storage>) -> Result<Vec<String>, String> {
Ok(float_list)
}


#[tauri::command]
fn get_decompiled_code(function_index: &str, app_data: State<Storage>) -> Result<String, String> {
let app_data = app_data.app_data.lock().map_err(|e| e.to_string())?;
Expand All @@ -202,10 +188,13 @@ fn get_decompiled_code(function_index: &str, app_data: State<Storage>) -> Result
let mut decompiled_code = String::new();

if let Some(f) = function {
decompiled_code = format!("{}", decompile_function(&bytecode, &f)
.display(&bytecode, &hlbc_decompiler::fmt::FormatOptions::new(2)));
decompiled_code = format!(
"{}",
decompile_function(bytecode, f)
.display(bytecode, &hlbc_decompiler::fmt::FormatOptions::new(2))
);
}

Ok(decompiled_code)
}

Expand All @@ -215,16 +204,21 @@ fn get_decompiled_type(type_index: &str, app_data: State<Storage>) -> Result<Str
let bytecode = app_data.bytecode.as_ref().ok_or("bytecode not loaded")?;
let types = &bytecode.types;

let tindex: usize = type_index[1..].parse().map_err(|_| "Invalid type index format")?;
let tindex: usize = type_index[1..]
.parse()
.map_err(|_| "Invalid type index format")?;
if tindex >= types.len() {
return Err("Type index out of bounds".to_string());
}

let type_obj = types[tindex].clone();
let decompiled_code = match type_obj {
Type::Obj(obj) => {
format!("{}", decompile_class(&bytecode, &obj)
.display(&bytecode, &hlbc_decompiler::fmt::FormatOptions::new(2)))
format!(
"{}",
decompile_class(bytecode, &obj)
.display(bytecode, &hlbc_decompiler::fmt::FormatOptions::new(2))
)
}
_ => return Err("Type is not an object".to_string()),
};
Expand All @@ -240,14 +234,26 @@ fn get_dashboard_info(app_data: State<Storage>) -> Result<String, String> {
let int_n = bytecode.ints.len();
let float_n = bytecode.floats.len();
let string_n = bytecode.strings.len();
let byte_n = bytecode.bytes.as_ref().map(|(bytes, _)| bytes.len()).unwrap_or(0);
let file_n = bytecode.debug_files.as_ref().map(|files| files.len()).unwrap_or(0);
let byte_n = bytecode
.bytes
.as_ref()
.map(|(bytes, _)| bytes.len())
.unwrap_or(0);
let file_n = bytecode
.debug_files
.as_ref()
.map(|files| files.len())
.unwrap_or(0);
let type_n = bytecode.types.len();
let global_n = bytecode.globals.len();
let native_n = bytecode.natives.len();
let function_n = bytecode.functions.len();
let constant_n = bytecode.constants.as_ref().map(|constants| constants.len()).unwrap_or(0);
let entrypoint = bytecode.entrypoint.display::<EnhancedFmt>(&bytecode);
let constant_n = bytecode
.constants
.as_ref()
.map(|constants| constants.len())
.unwrap_or(0);
let entrypoint = bytecode.entrypoint.display::<EnhancedFmt>(bytecode);

Ok(format!(
"File path: {}\nVersion: {}\nInts: {}\nFloats: {}\nStrings: {}\nBytes: {}\nFiles: {}\nTypes: {}\nGlobals: {}\nNatives: {}\nFunctions: {}\nConstants: {}\nEntrypoint: {}",
Expand All @@ -272,17 +278,17 @@ fn get_disassembled_code(function_index: &str, app_data: State<Storage>) -> Resu
let app_data = app_data.app_data.lock().map_err(|e| e.to_string())?;
let bytecode = app_data.bytecode.as_ref().ok_or("bytecode not loaded")?;
let functions = &bytecode.functions;

let mut function = None;
for f in functions {
if f.findex.to_string() == function_index {
function = Some(f);
break;
}
}
let disassembled_code = format!("{}", function.unwrap().display::<EnhancedFmt>(&bytecode));

let disassembled_code = format!("{}", function.unwrap().display::<EnhancedFmt>(bytecode));

Ok(disassembled_code)
}

Expand All @@ -292,40 +298,61 @@ fn get_disassembled_type(type_index: &str, app_data: State<Storage>) -> Result<S
let bytecode = app_data.bytecode.as_ref().ok_or("bytecode not loaded")?;
let types = &bytecode.types;

let tindex: usize = type_index[1..].parse().map_err(|_| "Invalid type index format")?;
let tindex: usize = type_index[1..]
.parse()
.map_err(|_| "Invalid type index format")?;
if tindex >= types.len() {
return Err("Type index out of bounds".to_string());
}

let type_obj = &types[tindex];
let disassembled_type = match type_obj {
Type::Obj(obj) => {
let mut disassembled_type = format!("{}", type_obj.display::<EnhancedFmt>(&bytecode));
let mut disassembled_type = format!("{}", type_obj.display::<EnhancedFmt>(bytecode));
if let Some(sup) = obj.super_ {
disassembled_type += &format!("\nextends {}", sup.display::<EnhancedFmt>(&bytecode));
disassembled_type +=
&format!("\nextends {}", sup.display::<EnhancedFmt>(bytecode));
}
disassembled_type += &format!("\nglobal: {}", obj.global.0);
disassembled_type += "\nfields:";
for f in &obj.own_fields {
disassembled_type += &format!("\n {}: {}", f.name.display::<EnhancedFmt>(&bytecode), f.t.display::<EnhancedFmt>(&bytecode));
disassembled_type += &format!(
"\n {}: {}",
f.name.display::<EnhancedFmt>(bytecode),
f.t.display::<EnhancedFmt>(bytecode)
);
}
disassembled_type += "\nprotos:";
for p in &obj.protos {
disassembled_type += &format!("\n {}: {} ({})", p.name.display::<EnhancedFmt>(&bytecode), bytecode.get(p.findex).display_header::<EnhancedFmt>(&bytecode), p.pindex);
disassembled_type += &format!(
"\n {}: {} ({})",
p.name.display::<EnhancedFmt>(bytecode),
bytecode
.get(p.findex)
.display_header::<EnhancedFmt>(bytecode),
p.pindex
);
}
disassembled_type += "\nbindings:";
for (fi, fun) in &obj.bindings {
disassembled_type += &format!("\n {}: {}", fi.display::<EnhancedFmt>(&bytecode, type_obj), fun.display_header::<EnhancedFmt>(&bytecode));
disassembled_type += &format!(
"\n {}: {}",
fi.display::<EnhancedFmt>(bytecode, type_obj),
fun.display_header::<EnhancedFmt>(bytecode)
);
}
disassembled_type
}
Type::Enum { global, constructs, .. } => {
Type::Enum {
global, constructs, ..
} => {
let mut disassembled_type = format!("global: {}", global.0);
disassembled_type += "\nconstructs:";
for c in constructs {
disassembled_type += &format!("\n {}:", c.name(&bytecode));
disassembled_type += &format!("\n {}:", c.name(bytecode));
for (i, p) in c.params.iter().enumerate() {
disassembled_type += &format!("\n {i}: {}", p.display::<EnhancedFmt>(&bytecode));
disassembled_type +=
&format!("\n {i}: {}", p.display::<EnhancedFmt>(bytecode));
}
}
disassembled_type
Expand All @@ -343,7 +370,7 @@ fn save_function_list(file_path: &str, app_data: State<Storage>) -> Result<(), S
let functions = &bytecode.functions;
let mut function_names = Vec::new();
for function in functions {
function_names.push(function.name(&bytecode).to_string() + &function.findex.to_string());
function_names.push(function.name(bytecode).to_string() + &function.findex.to_string());
}

let mut file = std::fs::File::create(file_path).map_err(|e| e.to_string())?;
Expand All @@ -362,8 +389,7 @@ fn save_type_list(file_path: &str, app_data: State<Storage>) -> Result<(), Strin
let mut type_names = Vec::new();
let mut index = 0;
for t in types {
type_names.push(t.display::<EnhancedFmt>(&bytecode).to_string() +
"@" + &index.to_string());
type_names.push(t.display::<EnhancedFmt>(bytecode).to_string() + "@" + &index.to_string());
index += 1;
}

Expand Down Expand Up @@ -399,20 +425,24 @@ fn save_file_list(file_path: &str, app_data: State<Storage>) -> Result<(), Strin
}

#[tauri::command]
fn save_disassembled_code(file_path: &str, function_index: &str, app_data: State<Storage>) -> Result<(), String> {
fn save_disassembled_code(
file_path: &str,
function_index: &str,
app_data: State<Storage>,
) -> Result<(), String> {
let app_data = app_data.app_data.lock().map_err(|e| e.to_string())?;
let bytecode = app_data.bytecode.as_ref().ok_or("bytecode not loaded")?;
let functions = &bytecode.functions;

let mut function = None;
for f in functions {
if f.findex.to_string() == function_index {
function = Some(f);
break;
}
}
let disassembled_code = format!("{}", function.unwrap().display::<EnhancedFmt>(&bytecode));

let disassembled_code = format!("{}", function.unwrap().display::<EnhancedFmt>(bytecode));

let mut file = std::fs::File::create(file_path).map_err(|e| e.to_string())?;
writeln!(file, "{}", disassembled_code).map_err(|e| e.to_string())?;
Expand Down Expand Up @@ -444,7 +474,10 @@ fn read_config(config_file_path: &str, app_handle: &tauri::AppHandle) -> Result<
Ok(())
}

fn create_default_config(config_file_path: &str, app_handle: &tauri::AppHandle) -> Result<(), String> {
fn create_default_config(
config_file_path: &str,
app_handle: &tauri::AppHandle,
) -> Result<(), String> {
let _ = std::fs::File::create(config_file_path).map_err(|e| e.to_string())?;
let default_config = AppConfig {
file_path: config_file_path.to_string(),
Expand Down Expand Up @@ -495,8 +528,11 @@ fn set_config_colorscheme(colorscheme: &str, app_data: State<Storage>) -> Result
#[tauri::command]
fn add_config_recent_file(file_path: &str, app_data: State<Storage>) -> Result<(), String> {
let mut app_data = app_data.app_data.lock().map_err(|e| e.to_string())?;
let recent_files = app_data.app_config.recent_files.get_or_insert_with(|| Vec::new());

let recent_files = app_data
.app_config
.recent_files
.get_or_insert_with(Vec::new);

if !recent_files.contains(&file_path.to_string()) {
recent_files.push(file_path.to_string());
}
Expand All @@ -514,18 +550,25 @@ fn get_config_theme(app_data: State<Storage>) -> Result<String, String> {
#[tauri::command]
fn get_config_colorscheme(app_data: State<Storage>) -> Result<String, String> {
let app_data = app_data.app_data.lock().map_err(|e| e.to_string())?;
let colorscheme = app_data.app_config.colorscheme.as_ref().ok_or("colorscheme not set")?;
let colorscheme = app_data
.app_config
.colorscheme
.as_ref()
.ok_or("colorscheme not set")?;
Ok(colorscheme.to_string())
}

#[tauri::command]
fn get_config_recent_files(app_data: State<Storage>) -> Result<Vec<String>, String> {
let app_data = app_data.app_data.lock().map_err(|e| e.to_string())?;
let recent_files = app_data.app_config.recent_files.as_ref().ok_or("recent_files not set")?;
let recent_files = app_data
.app_config
.recent_files
.as_ref()
.ok_or("recent_files not set")?;
Ok(recent_files.clone())
}


#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
Expand Down