neo-decompiler 0.11.0

Neo N3 NEF decompiler: parse, disassemble, lift bytecode to high-level pseudocode and C# skeletons, with a CLI, JSON reports, and optional WebAssembly bindings.
Documentation
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(())
    }
}