use crate::api::{self, cache};
use crate::structs::core::Class;
use std::ffi::c_void;
use super::assembly::Assembly;
#[derive(Debug, Clone)]
pub struct Image {
pub address: *mut c_void,
pub name: String,
pub filename: String,
pub assembly: *mut c_void,
pub entry_point: *mut c_void,
}
unsafe impl Send for Image {}
unsafe impl Sync for Image {}
impl Image {
pub fn get_assembly(&self) -> Option<std::sync::Arc<Assembly>> {
unsafe {
let assembly_ptr = api::image_get_assembly(self.address);
if assembly_ptr.is_null() {
return None;
}
for entry in cache::CACHE.assemblies.iter() {
if entry.value().address == assembly_ptr {
return Some(std::sync::Arc::clone(entry.value()));
}
}
None
}
}
pub fn get_classes(&self) -> Vec<Class> {
let mut classes = Vec::new();
unsafe {
let class_count = api::image_get_class_count(self.address);
for i in 0..class_count {
let class_ptr = api::image_get_class(self.address, i);
if !class_ptr.is_null() {
if let Some(class) = cache::class_from_ptr(class_ptr) {
classes.push(class);
}
}
}
}
classes
}
pub fn class(&self, name: &str) -> Option<Class> {
if let Some(class) = cache::CACHE.classes.get(name) {
return Some((**class).clone());
}
let (namespace, class_name) = if let Some(idx) = name.rfind('.') {
(&name[..idx], &name[idx + 1..])
} else {
("", name)
};
unsafe {
let ns_cstr = std::ffi::CString::new(namespace).ok()?;
let name_cstr = std::ffi::CString::new(class_name).ok()?;
let class_ptr =
api::class_from_name(self.address, ns_cstr.as_ptr(), name_cstr.as_ptr());
if !class_ptr.is_null() {
cache::class_from_ptr(class_ptr)
} else {
None
}
}
}
}