use std::io::Write as _;
use std::path::Path;
use crate::disassembler::Disassembler;
use crate::error::Result;
use crate::nef::NefParser;
use crate::util;
use super::super::args::{Cli, DisasmFormat};
use super::super::reports::{DisasmReport, InstructionReport};
impl Cli {
pub(super) fn run_disasm(
&self,
path: &Path,
format: DisasmFormat,
fail_on_unknown_opcodes: bool,
) -> Result<()> {
let handling = Self::unknown_handling(fail_on_unknown_opcodes);
let bytes = Self::read_nef_bytes(path)?;
let parse_output = NefParser::new().parse_with_warnings(&bytes)?;
let nef = parse_output.nef;
let result =
Disassembler::with_unknown_handling(handling).disassemble_with_warnings(&nef.script)?;
let mut warnings = parse_output
.warnings
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>();
warnings.extend(result.warnings.iter().map(ToString::to_string));
match format {
DisasmFormat::Text => {
self.write_stdout(|out| {
for instruction in &result.instructions {
match instruction.operand {
Some(ref operand) => {
writeln!(
out,
"{:04X}: {:<10} {}",
instruction.offset, instruction.opcode, operand
)?;
}
None => {
writeln!(
out,
"{:04X}: {}",
instruction.offset, instruction.opcode
)?;
}
}
}
Self::write_warnings(out, &warnings)
})?;
}
DisasmFormat::Json => {
let instructions: Vec<InstructionReport> = result
.instructions
.iter()
.map(InstructionReport::from)
.collect();
let script_hash = nef.script_hash();
let report = DisasmReport {
file: path.display().to_string(),
script_hash_le: util::format_hash(&script_hash),
script_hash_be: util::format_hash_be(&script_hash),
instructions,
warnings,
};
self.print_json(&report)?;
}
}
Ok(())
}
}