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 serde::Serialize;

use crate::native_contracts;
use crate::nef::{call_flag_labels, describe_call_flags, MethodToken};
use crate::util;

#[derive(Debug, Clone, Serialize)]
pub(super) struct MethodTokenReport {
    method: String,
    hash_le: String,
    hash_be: String,
    parameters: u16,
    returns: bool,
    call_flags: u8,
    call_flags_description: String,
    call_flag_labels: Vec<&'static str>,
    returns_value: bool,
    native_contract: Option<NativeContractReport>,
    pub(super) warning: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
struct NativeContractReport {
    contract: String,
    method: Option<String>,
    label: String,
}

pub(super) fn build_method_token_report(token: &MethodToken) -> MethodTokenReport {
    let hint = native_contracts::describe_method_token(&token.hash, &token.method);
    let warning = hint.as_ref().and_then(|h| {
        if h.has_exact_method() {
            None
        } else {
            Some(format!(
                "native contract {} does not expose method {}",
                h.contract, token.method
            ))
        }
    });
    let native_contract = hint.as_ref().map(|h| NativeContractReport {
        contract: h.contract.to_string(),
        method: h.canonical_method.map(ToString::to_string),
        label: h.formatted_label(&token.method),
    });

    MethodTokenReport {
        method: token.method.clone(),
        hash_le: util::format_hash(&token.hash),
        hash_be: util::format_hash_be(&token.hash),
        parameters: token.parameters_count,
        returns: token.has_return_value,
        call_flags: token.call_flags,
        call_flags_description: describe_call_flags(token.call_flags),
        call_flag_labels: call_flag_labels(token.call_flags),
        returns_value: token.has_return_value,
        native_contract,
        warning,
    }
}

pub(super) fn collect_warnings(tokens: &[MethodTokenReport]) -> Vec<String> {
    tokens
        .iter()
        .filter_map(|report| report.warning.as_ref().map(ToString::to_string))
        .collect()
}