use core::{ffi::c_void, mem::transmute};
use macros::Object;
use sys::cpp::HasVtable;
use crate::mt::{dti::MtDti, property_list::MtPropertyList};
#[derive(Object)]
pub struct MtObject;
impl MtObject {
pub fn dti(&self) -> &'static MtDti {
self.get_dti()
}
pub fn get_properties(&self) -> MtPropertyList {
let mut props = MtPropertyList::new();
self.create_property(&mut props);
props
}
pub fn to<T: Object>(&self) -> &T {
unsafe { &*(self as *const Self as *const T) }
}
pub fn to_mut<T: Object>(&mut self) -> &mut T {
unsafe { &mut *(self as *mut Self as *mut T) }
}
}
pub trait Object: HasVtable {
fn dtor(&mut self) {
let func: unsafe extern "C" fn(&mut Self) = unsafe { transmute(self.get_virtual_function(0)) };
unsafe { func(self) }
}
fn destroy(&mut self) {
let func: unsafe extern "C" fn(&mut Self) = unsafe { transmute(self.get_virtual_function(1)) };
unsafe { func(self) }
}
fn create_ui(&self) {
let func: unsafe extern "C" fn(&Self) = unsafe { transmute(self.get_virtual_function(2)) };
unsafe { func(self) }
}
fn is_enable_instance(&self) -> bool {
let func: unsafe extern "C" fn(&Self) -> bool = unsafe { transmute(self.get_virtual_function(3)) };
unsafe { func(self) }
}
fn create_property(&self, props: &mut MtPropertyList) {
let func: unsafe extern "C" fn(&Self, *mut MtPropertyList) = unsafe { transmute(self.get_virtual_function(4)) };
unsafe { func(self, props as *mut MtPropertyList) }
}
fn get_dti(&self) -> &'static MtDti {
let func: unsafe extern "C" fn(&Self) -> *const c_void = unsafe { transmute(self.get_virtual_function(5)) };
let dti = unsafe { func(self) };
unsafe { &*(dti as *const MtDti) }
}
fn to_mt_object(&self) -> &MtObject {
let ptr = self as *const Self as *const MtObject;
unsafe { &*ptr }
}
fn to_mut_mt_object(&mut self) -> &mut MtObject {
let ptr = self as *mut Self as *mut MtObject;
unsafe { &mut *ptr }
}
unsafe fn read<T>(&self, offset: usize) -> T {
let ptr = self as *const Self as *const u8;
unsafe { (ptr.add(offset) as *const T).read_unaligned() }
}
unsafe fn write<T: Copy>(&mut self, offset: usize, value: &T) {
let ptr = self as *mut Self as *mut u8;
unsafe { *(ptr.add(offset) as *mut T) = *value };
}
unsafe fn get_ref<T>(&self, offset: usize) -> &T {
let ptr = self as *const Self as *const u8;
unsafe { &*(ptr.add(offset) as *const T) }
}
unsafe fn get_mut_ref<T>(&mut self, offset: usize) -> &mut T {
let ptr = self as *mut Self as *mut u8;
unsafe { &mut *(ptr.add(offset) as *mut T) }
}
}