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()
}