use rustc_hash::FxHashMap;
use crate::assembly::Instruction;
pub struct MethodCode {
instructions: Vec<Instruction>,
base_rva: u64,
offset_to_index: FxHashMap<u32, u32>,
}
impl MethodCode {
#[must_use]
pub fn new(instructions: Vec<Instruction>) -> Option<Self> {
let base_rva = instructions.first()?.rva;
let mut offset_to_index = FxHashMap::default();
offset_to_index.reserve(instructions.len());
for (index, instr) in instructions.iter().enumerate() {
let offset = instr.rva.saturating_sub(base_rva);
if let (Ok(offset), Ok(index)) = (u32::try_from(offset), u32::try_from(index)) {
offset_to_index.insert(offset, index);
}
}
Some(MethodCode {
instructions,
base_rva,
offset_to_index,
})
}
#[must_use]
pub fn base_rva(&self) -> u64 {
self.base_rva
}
#[must_use]
pub fn instructions(&self) -> &[Instruction] {
&self.instructions
}
#[must_use]
pub fn instruction_at(&self, offset: u32) -> Option<&Instruction> {
let index = *self.offset_to_index.get(&offset)?;
self.instructions.get(index as usize)
}
#[must_use]
#[allow(clippy::cast_possible_truncation)]
pub fn rva_to_offset(&self, rva: u64) -> u32 {
rva.saturating_sub(self.base_rva) as u32
}
}