use lief_ffi as ffi;
use std::marker::PhantomData;
use crate::DeclOpt;
use crate::Range;
use crate::common::{FromFFI, into_optional, into_ranges};
use crate::declare_fwd_iterator;
use super::{Function, Variable};
use crate::dwarf::function::Functions;
use crate::dwarf::types::Types;
use crate::dwarf::variable::CompilationUnitVariables;
pub struct CompilationUnit<'a> {
ptr: cxx::UniquePtr<ffi::DWARF_CompilationUnit>,
_owner: PhantomData<&'a ()>,
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Langs {
C,
CPP,
RUST,
DART,
MODULA,
FORTRAN,
SWIFT,
D,
JAVA,
COBOL,
UNKNOWN(u32),
}
impl From<u32> for Langs {
fn from(value: u32) -> Self {
match value {
0x00000001 => Langs::C,
0x00000002 => Langs::CPP,
0x00000003 => Langs::RUST,
0x00000004 => Langs::DART,
0x00000005 => Langs::MODULA,
0x00000006 => Langs::FORTRAN,
0x00000007 => Langs::SWIFT,
0x00000008 => Langs::D,
0x00000009 => Langs::JAVA,
0x0000000A => Langs::COBOL,
_ => Langs::UNKNOWN(value),
}
}
}
impl From<Langs> for u32 {
fn from(value: Langs) -> u32 {
match value {
Langs::C => 0x00000001,
Langs::CPP => 0x00000002,
Langs::RUST => 0x00000003,
Langs::DART => 0x00000004,
Langs::MODULA => 0x00000005,
Langs::FORTRAN => 0x00000006,
Langs::SWIFT => 0x00000007,
Langs::D => 0x00000008,
Langs::JAVA => 0x00000009,
Langs::COBOL => 0x0000000A,
Langs::UNKNOWN(_) => 0,
}
}
}
#[derive(Debug)]
pub struct Language {
pub lang: Langs,
pub version: u32,
}
impl Language {
fn from_ffi(ffi_lang: ffi::DWARF_CompilationUnit_Language) -> Self {
Self {
lang: Langs::from(ffi_lang.lang),
version: ffi_lang.version,
}
}
}
impl FromFFI<ffi::DWARF_CompilationUnit> for CompilationUnit<'_> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::DWARF_CompilationUnit>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl CompilationUnit<'_> {
pub fn name(&self) -> String {
self.ptr.name().to_string()
}
pub fn producer(&self) -> String {
self.ptr.producer().to_string()
}
pub fn compilation_dir(&self) -> String {
self.ptr.compilation_dir().to_string()
}
pub fn language(&self) -> Language {
Language::from_ffi(self.ptr.language())
}
pub fn low_address(&self) -> u64 {
self.ptr.low_address()
}
pub fn high_address(&self) -> u64 {
self.ptr.high_address()
}
pub fn size(&self) -> u64 {
self.ptr.size()
}
pub fn ranges(&self) -> Vec<Range> {
into_ranges(self.ptr.ranges())
}
pub fn functions(&self) -> Functions<'_> {
Functions::new(self.ptr.functions())
}
pub fn imported_functions(&self) -> Functions<'_> {
Functions::new(self.ptr.imported_functions())
}
pub fn variables(&self) -> CompilationUnitVariables<'_> {
CompilationUnitVariables::new(self.ptr.variables())
}
pub fn types(&self) -> Types<'_> {
Types::new(self.ptr.types())
}
pub fn function_by_name(&self, name: &str) -> Option<Function<'_>> {
cxx::let_cxx_string!(__cxx_s = name);
into_optional(self.ptr.function_by_name(&__cxx_s))
}
pub fn function_by_addr(&self, address: u64) -> Option<Function<'_>> {
into_optional(self.ptr.function_by_address(address))
}
pub fn variable_by_name(&self, name: &str) -> Option<Variable<'_>> {
cxx::let_cxx_string!(__cxx_s = name);
into_optional(self.ptr.variable_by_name(&__cxx_s))
}
pub fn variable_by_addr(&self, address: u64) -> Option<Variable<'_>> {
into_optional(self.ptr.variable_by_address(address))
}
pub fn to_decl(&self) -> String {
self.ptr.to_decl().to_string()
}
pub fn to_decl_with_opt(&self, opt: &DeclOpt) -> String {
self.ptr.to_decl_with_opt(&opt.to_ffi()).to_string()
}
}
declare_fwd_iterator!(
CompilationUnits,
CompilationUnit<'a>,
ffi::DWARF_CompilationUnit,
ffi::DWARF_DebugInfo,
ffi::DWARF_DebugInfo_it_compilation_units
);