use lief_ffi as ffi;
use bitflags::bitflags;
use std::{fmt, marker::PhantomData};
use crate::common::{FromFFI, into_optional};
use super::{Symbol, commands::Dylib};
pub struct ExportInfo<'a> {
ptr: cxx::UniquePtr<ffi::MachO_ExportInfo>,
_owner: PhantomData<&'a ()>,
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Kind {
REGULAR,
THREAD_LOCAL,
ABSOLUTE,
UNKNOWN(u64),
}
impl From<u64> for Kind {
fn from(value: u64) -> Self {
match value {
0x00000000 => Kind::REGULAR,
0x00000001 => Kind::THREAD_LOCAL,
0x00000002 => Kind::ABSOLUTE,
_ => Kind::UNKNOWN(value),
}
}
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Flags: u64 {
const WEAK_DEFINITION = 0x4;
const REEXPORT = 0x8;
const STUB_AND_RESOLVER = 0x10;
const STATIC_RESOLVER = 0x20;
}
}
impl From<u64> for Flags {
fn from(value: u64) -> Self {
Flags::from_bits_truncate(value)
}
}
impl From<Flags> for u64 {
fn from(value: Flags) -> Self {
value.bits()
}
}
impl std::fmt::Display for Flags {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
bitflags::parser::to_writer(self, f)
}
}
impl fmt::Debug for ExportInfo<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ExportInfo")
.field("node_offset", &self.node_offset())
.field("flags", &self.flags())
.field("address", &self.address())
.field("other", &self.other())
.field("kind", &self.kind())
.finish()
}
}
impl ExportInfo<'_> {
pub fn node_offset(&self) -> u64 {
self.ptr.node_offset()
}
pub fn flags(&self) -> Flags {
Flags::from(self.ptr.flags())
}
pub fn address(&self) -> u64 {
self.ptr.address()
}
pub fn other(&self) -> u64 {
self.ptr.other()
}
pub fn kind(&self) -> Kind {
Kind::from(self.ptr.kind())
}
pub fn symbol(&self) -> Option<Symbol<'_>> {
into_optional(self.ptr.symbol())
}
pub fn alias(&self) -> Option<Symbol<'_>> {
into_optional(self.ptr.alias())
}
pub fn alias_library(&self) -> Option<Dylib<'_>> {
into_optional(self.ptr.alias_library())
}
}
impl<'a> FromFFI<ffi::MachO_ExportInfo> for ExportInfo<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_ExportInfo>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}