use std::{mem::transmute, str::FromStr}; use giterated_abi::vtable::IntoObjectVTable; use giterated_models::object::GiteratedObject; use crate::FFIBox; // #[derive(Clone, Copy)] // #[repr(C)] // pub struct ObjectVtable { // object_kind: *const u8, // object_kind_len: usize, // pub to_str: unsafe extern "C" fn(&AnyObject) -> FFIBox<[u8]>, // pub from_str: unsafe extern "C" fn(&str) -> Result>, // pub home_uri: unsafe extern "C" fn(&AnyObject) -> FFIBox, // pub is_same: unsafe extern "C" fn(&AnyObject) -> bool, // } // impl ObjectVtable { // pub fn new() -> Self { // let object_kind = T::object_kind().as_ptr(); // let object_kind_len = T::object_kind().len(); // Self { // to_str: T::to_str, // from_str: T::from_str, // home_uri: T::home_uri, // is_same: T::is_same, // object_kind, // object_kind_len, // } // } // pub fn kind(&self) -> &'static str { // let slice = unsafe { std::slice::from_raw_parts(self.object_kind, self.object_kind_len) }; // std::str::from_utf8(slice).unwrap() // } // } // pub trait IntoObjectVTable { // fn object_kind() -> &'static str; // unsafe extern "C" fn to_str(this: &AnyObject) -> FFIBox<[u8]>; // unsafe extern "C" fn from_str(src: &str) -> Result>; // unsafe extern "C" fn home_uri(this: &AnyObject) -> FFIBox; // unsafe extern "C" fn is_same(other: &AnyObject) -> bool; // } impl IntoObjectVTable for T { unsafe extern "C" fn to_str(this: &AnyObject) -> FFIBox<[u8]> { let this: &Box = this.transmute_ref(); let result = this.to_string(); FFIBox::from_box(result.into_bytes().into_boxed_slice()) } unsafe extern "C" fn from_str(src: &str) -> Result> { let result = T::from_object_str(src) .map_err(|err| FFIBox::from_box(err.to_string().into_boxed_str()))?; let any_object = AnyObject::new(result); Ok(any_object) } unsafe extern "C" fn home_uri(_this: &AnyObject) -> FFIBox { todo!() } fn object_kind() -> &'static std::ffi::CStr { ::object_name() } // unsafe extern "C" fn is_same(_other: &AnyObject) -> bool { // todo!() // } } // impl AnyObject { // pub fn new(inner: T) -> Self { // Self { // inner: FFIBox::from_box(Box::new(inner)).untyped(), // vtable: ObjectVtable::new::(), // } // } // pub fn vtable(&self) -> ObjectVtable { // self.vtable // } // pub fn object_kind(&self) -> &str { // unsafe { // std::str::from_utf8_unchecked(std::slice::from_raw_parts( // self.vtable.object_kind, // self.vtable.object_kind_len, // )) // } // } // pub fn home_uri(&self) -> String { // unsafe { (self.vtable.home_uri)(self).to_string() } // } // pub fn is_same(&self, other: &AnyObject) -> bool { // unsafe { (self.vtable.is_same)(other) } // } // pub unsafe fn cast(self) -> T { // assert_eq!(self.object_kind(), T::object_kind()); // info!("{}", self.to_string()); // T::from_object_str(&self.to_string()).unwrap() // } // } // impl ToString for AnyObject { // fn to_string(&self) -> String { // let slice: Box<[u8]> = unsafe { Box::from_raw((self.vtable.to_str)(&self).0 as *mut _) }; // let string = unsafe { std::str::from_boxed_utf8_unchecked(slice) }; // String::from(string) // } // } impl AnyObject { pub unsafe fn transmute_owned(&mut self) -> Box { Box::from_raw(self.inner.0 as *mut T) } pub unsafe fn transmute_ref(&self) -> &T { let ptr: *const T = transmute(self.inner.0); ptr.as_ref().unwrap() } }