use std::sync::Once;
use crate::arch::codec::{ArchCodec, ArchError};
use crate::ast::{Module, Value};
static REGISTER_ALL: Once = Once::new();
pub fn resolve_arch_codec(module: &Module) -> Result<Box<dyn ArchCodec>, ArchError> {
REGISTER_ALL.call_once(crate::translate::register_all_arches);
let arch_name = module_arch_name(module);
let e_machine = module_e_machine(module);
crate::arch::codec::for_arch(arch_name.as_deref(), e_machine)
}
fn module_arch_name(module: &Module) -> Option<String> {
module.fields.iter().find_map(|f| {
if f.name != "arch" {
return None;
}
match &f.value {
Value::String(s) => Some(s.to_ascii_lowercase()),
_ => None,
}
})
}
fn module_e_machine(module: &Module) -> Option<u64> {
let build = module.fields.iter().find_map(|f| {
if f.name != "build" {
return None;
}
match &f.value {
Value::Block(fields) => Some(fields),
_ => None,
}
})?;
build.iter().find_map(|f| {
if f.name != "e_machine" {
return None;
}
match &f.value {
Value::Int(n) => Some(*n),
_ => None,
}
})
}