use std::{hash::Hash, path::PathBuf};
use gimli::{Unit, UnitSectionOffset};
use crate::{
die::utils::get_dwarf,
file::{DebugFile, DwarfReader},
DwarfDb,
};
pub type UnitRef<'a, R = DwarfReader> = gimli::UnitRef<'a, R>;
#[derive(Debug)]
struct DwarfUnit {
file_path: PathBuf,
offset: UnitSectionOffset<usize>,
unit: Unit<DwarfReader>,
}
impl PartialEq for DwarfUnit {
fn eq(&self, other: &Self) -> bool {
self.file_path == other.file_path && self.offset == other.offset
}
}
impl Eq for DwarfUnit {}
impl Hash for DwarfUnit {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.file_path.hash(state);
self.offset.hash(state);
}
}
unsafe impl salsa::Update for DwarfUnit {
unsafe fn maybe_update(_: *mut Self, _: Self) -> bool {
false
}
}
pub fn get_unit_ref<'db>(
db: &'db dyn DwarfDb,
file: DebugFile,
cu_offset: UnitSectionOffset<usize>,
) -> Option<UnitRef<'db, DwarfReader>> {
#[salsa::tracked(returns(ref))]
fn get_unit<'db>(
db: &'db dyn DwarfDb,
file: DebugFile,
cu_offset: UnitSectionOffset<usize>,
) -> Option<DwarfUnit> {
let dwarf = get_dwarf(db, file.file(db))?;
let mut units = dwarf.units();
while let Ok(Some(header)) = units.next() {
if header.offset() == cu_offset {
return Some(DwarfUnit {
file_path: file.file(db).path(db).clone(),
offset: cu_offset,
unit: dwarf.unit(header).unwrap(),
});
}
}
None
}
let unit = &get_unit(db, file, cu_offset).as_ref()?.unit;
let dwarf = get_dwarf(db, file.file(db))?;
Some(UnitRef { dwarf, unit })
}