use nrbf_parser::Decoder;
use nrbf_parser::Encoder;
use nrbf_parser::interleaved::{from_interleaved, to_interleaved};
use nrbf_parser::records::Record;
use std::env;
use std::fs::File;
use std::io::{BufReader, BufWriter, Read};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
eprintln!("Usage: {} <nrbf_file>", args[0]);
std::process::exit(1);
}
let input_path = &args[1];
println!("Reading original file: {}", input_path);
let file = File::open(input_path)?;
let mut original_data = Vec::new();
File::open(input_path)?.read_to_end(&mut original_data)?;
let reader = BufReader::new(file);
let mut decoder = Decoder::new(reader);
let mut records = Vec::new();
while let Some(record) = decoder.decode_next()? {
let is_end = matches!(record, Record::MessageEnd);
records.push(record);
if is_end {
break;
}
}
println!("Parsed {} records.", records.len());
let json = serde_json::to_string_pretty(&records)?;
let json_path = "output.json";
std::fs::write(json_path, &json)?;
println!("Saved records to {}", json_path);
let interleaved_json = to_interleaved(&records);
let interleaved_json_str = serde_json::to_string_pretty(&interleaved_json)?;
let interleaved_path = "interleaved.json";
std::fs::write(interleaved_path, &interleaved_json_str)?;
println!("Saved interleaved records to {}", interleaved_path);
let deserialized_records: Vec<Record> = serde_json::from_str(&json)?;
println!(
"Deserialized {} records from JSON.",
deserialized_records.len()
);
let output_path = "reconstructed.meta";
let out_file = File::create(output_path)?;
let mut encoder = Encoder::new(BufWriter::new(out_file));
for record in &deserialized_records {
encoder.encode(record)?;
}
drop(encoder);
println!("Reconstructed binary saved to {}", output_path);
println!("--- Interleaved Round Trip Check ---");
let interleaved_reconstructed_records = from_interleaved(interleaved_json);
println!(
"Deserialized {} records from Interleaved JSON.",
interleaved_reconstructed_records.len()
);
let interleaved_output_path = "reconstructed_interleaved.meta";
let int_out_file = File::create(interleaved_output_path)?;
let mut int_encoder = Encoder::new(BufWriter::new(int_out_file));
for record in &interleaved_reconstructed_records {
int_encoder.encode(record)?;
}
drop(int_encoder);
let mut int_reconstructed_data = Vec::new();
File::open(interleaved_output_path)?.read_to_end(&mut int_reconstructed_data)?;
if original_data == int_reconstructed_data {
println!("SUCCESS: Interleaved reconstructed binary is identical to original!");
} else {
println!("FAILURE: Interleaved reconstructed binary differs from original.");
println!(
"Original size: {}, Reconstructed size: {}",
original_data.len(),
int_reconstructed_data.len()
);
let min_len = std::cmp::min(original_data.len(), int_reconstructed_data.len());
for i in 0..min_len {
if original_data[i] != int_reconstructed_data[i] {
println!(
"First difference at offset 0x{:x}: original 0x{:02x}, reconstructed 0x{:02x}",
i, original_data[i], int_reconstructed_data[i]
);
break;
}
}
}
Ok(())
}