#![allow(unused_must_use)]
use super::Endian;
use std::io::prelude::*;
use std::path::Path;
use std::sync::{
atomic::{AtomicUsize, Ordering},
Mutex,
};
use lazy_static::lazy_static;
lazy_static! {
static ref FILE: Mutex<Option<Box<dyn Write + Send>>> = Mutex::new({
std::env::var("DEBUG_TEMPLATE")
.ok()
.map(|path| {
let mut file = std::fs::File::create(path).ok()?;
write!(file, "{}", SETUP).ok()?;
Some(file)
})
.flatten()
.map(|file| Box::new(file) as _)
});
}
static CURRENT_STRUCT_NUM: AtomicUsize = AtomicUsize::new(0);
static CURRENT_VAR_NUM: AtomicUsize = AtomicUsize::new(0);
const SETUP: &str =
"// Generated by BinRead macro by jam1garner (https://github.com/jam1garner/binread)
typedef char i8;
typedef uchar u8;
typedef int16 i16;
typedef uint16 u16;
typedef int32 i32;
typedef uint32 u32;
typedef int64 i64;
typedef uint64 u64;
typedef float f32;
typedef double f64;
";
const COLORS: &[&str] = &[
"0xE85EBE", "0xFF6E41", "0x00FFC6", "0x788231", "0x00B917", "0x85A900", "0x0076FF", "0x006401",
"0x009BFF", "0x00FF78", "0xDEFF74", "0xE56FFE", "0xBDD393", "0x7E2DD2", "0x90FB92", "0xFFDB66",
"0xFFB167", "0xB500FF", "0x43002C", "0x004754", "0x263400", "0x7A4782", "0x774D00", "0xFFA6FE",
"0xA5FFD2", "0x7544B1", "0xBB8800", "0x01D0FF", "0xBDC6FF", "0xFE8900", "0xFFEEE8", "0x01FFFE",
"0xA75740", "0x98FF52", "0x968AE8", "0xFF74A3", "0x683D3B", "0xFF029D", "0xFF00F6", "0xFF0000",
"0x5FAD4E", "0x008F9C", "0xBE9970", "0xC28C9F", "0x00AE7E", "0x6A826C", "0x007DB5", "0x0000FF",
"0x6B6882", "0x620E00", "0x91D0CB", "0x001544", "0xA42400", "0xFF937E", "0x95003A", "0x00FF00",
"0x005F39", "0xFFE502", "0x0E4CA1", "0x9E008E", "0xFF0056", "0xD5FF00", "0x010067", "0x000000",
];
pub fn set_output_file<P: AsRef<Path>>(path: P) -> std::io::Result<()> {
set_output(std::fs::File::create(path.as_ref())?);
Ok(())
}
pub fn set_output<W: Write + Send + 'static>(mut writer: W) {
writeln!(writer, "{}", SETUP);
*FILE.lock().unwrap() = Some(Box::new(writer));
}
pub fn unset_output() {
*FILE.lock().unwrap() = None;
}
pub fn write_named(endian: Endian, pos: u64, type_name: &str, var_name: &str) {
let mut lock = FILE.lock().unwrap();
let file = match lock.as_mut() {
Some(x) => x,
None => return,
};
match endian {
Endian::Big => writeln!(*file, "BigEndian();"),
Endian::Little => writeln!(*file, "LittleEndian();"),
_ => writeln!(*file),
};
let color_index = CURRENT_VAR_NUM.fetch_add(1, Ordering::SeqCst) & 0x3f;
writeln!(*file, "FSeek(0x{:X});", pos);
writeln!(
*file,
"{} {}<bgcolor={}>;\n",
type_name, var_name, COLORS[color_index]
);
}
pub fn get_next_var_name() -> String {
let var_num = CURRENT_VAR_NUM.fetch_add(1, Ordering::SeqCst);
format!("var{}", var_num)
}
pub fn get_next_color() -> &'static str {
let color_index = CURRENT_VAR_NUM.fetch_add(1, Ordering::SeqCst) & 0x3f;
COLORS[color_index]
}
pub fn write_start_struct(name: &str) {
let mut lock = FILE.lock().unwrap();
let file = match lock.as_mut() {
Some(x) => x,
None => return,
};
writeln!(
*file,
"struct {}_{} {{",
name,
CURRENT_STRUCT_NUM.fetch_add(1, Ordering::SeqCst)
);
}
pub fn write_comment(comment: &str) {
let mut lock = FILE.lock().unwrap();
let file = match lock.as_mut() {
Some(x) => x,
None => return,
};
writeln!(*file, "// {}", comment);
}
pub fn write_end_struct(name: Option<&str>) {
let mut lock = FILE.lock().unwrap();
let file = match lock.as_mut() {
Some(x) => x,
None => return,
};
let var_name = name.unwrap_or("root");
writeln!(*file, "}} {};", var_name);
}
pub fn write(endian: Endian, pos: u64, type_name: &str) {
let var_name = get_next_var_name();
write_named(endian, pos, type_name, &var_name);
}
pub fn write_vec_named(endian: Endian, pos: u64, type_name: &str, count: usize, name: &str) {
let mut lock = FILE.lock().unwrap();
let file = match lock.as_mut() {
Some(x) => x,
None => return,
};
match endian {
Endian::Big => writeln!(*file, "BigEndian();"),
Endian::Little => writeln!(*file, "LittleEndian();"),
_ => writeln!(*file),
};
let color_index = CURRENT_VAR_NUM.fetch_add(1, Ordering::SeqCst) & 0x3f;
writeln!(*file, "FSeek(0x{:X});", pos);
writeln!(
*file,
"{} {}[{}]<bgcolor={}>;\n",
type_name, name, count, COLORS[color_index]
);
}
pub fn write_vec(endian: Endian, pos: u64, type_name: &str, count: usize) {
let var_num = CURRENT_VAR_NUM.fetch_add(1, Ordering::SeqCst);
write_vec_named(endian, pos, type_name, count, &format!("var{}", var_num))
}