use std::mem::transmute; use giterated_models::{ instance::Instance, settings::{GetSetting, Setting}, }; use crate::{AnySuccess, FFIBox}; use super::OperationVTable; #[repr(C)] pub struct NewAnySetting { /// A pointer to the plugin-local object type. We are not capable of /// knowing what this type is, we use the provided vtable. inner: FFIBox<()>, pub vtable: SettingVtable, } impl NewAnySetting { pub fn new(value: V) -> Self { Self { inner: FFIBox::from_box(Box::new(value)).untyped(), vtable: SettingVtable::new::(), } } pub unsafe fn transmute_owned(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() } } impl From for AnySuccess { fn from(val: NewAnySetting) -> Self { unsafe { AnySuccess::from_raw(val.inner, (val.vtable.get_setting_vtable)()) } } } #[derive(Clone, Copy)] #[repr(C)] pub struct SettingVtable { pub get_setting_vtable: unsafe extern "C" fn() -> OperationVTable, pub deserialize: unsafe extern "C" fn(&[u8]) -> Result<(), ()>, pub serialize: unsafe extern "C" fn(NewAnySetting) -> Result, ()>, } impl SettingVtable { pub fn new() -> Self { Self { get_setting_vtable: T::get_setting_vtable, deserialize: T::deserialize, serialize: T::serialize, } } } pub trait IntoSettingVTable { unsafe extern "C" fn get_setting_vtable() -> OperationVTable; unsafe extern "C" fn deserialize(src: &[u8]) -> Result<(), ()>; unsafe extern "C" fn serialize(this: NewAnySetting) -> Result, ()>; } impl IntoSettingVTable for S where S: Setting, { unsafe extern "C" fn deserialize(_src: &[u8]) -> Result<(), ()> { todo!() } unsafe extern "C" fn serialize(this: NewAnySetting) -> Result, ()> { let setting = this.transmute_owned::(); let serialized = serde_json::to_vec(&setting).unwrap(); let serialized = serialized.into_boxed_slice(); Ok(FFIBox::from_box(serialized)) } unsafe extern "C" fn get_setting_vtable() -> OperationVTable { OperationVTable::new::() } }