use giterated_models::{ object::GiteratedObject, value::{GetValue, GiteratedObjectValue}, }; use crate::{AnySuccess, FFIBox}; use super::OperationVTable; #[repr(C)] pub struct NewAnyValue { /// 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<()>, vtable: ValueVTable, } unsafe impl Send for NewAnyValue {} unsafe impl Sync for NewAnyValue {} impl NewAnyValue { pub fn new + Send + Sync>(value: V) -> Self { NewAnyValue { inner: FFIBox::from_box(Box::new(value)).untyped(), vtable: ValueVTable::new::(), } } } impl From for AnySuccess { fn from(val: NewAnyValue) -> Self { unsafe { AnySuccess::from_raw(val.inner, (val.vtable.get_value_vtable)()) } } } #[derive(Clone, Copy)] #[repr(C)] pub struct ValueVTable { pub get_value_vtable: unsafe extern "C" fn() -> OperationVTable, pub deserialize: unsafe extern "C" fn(&[u8]) -> Result, pub serialize: unsafe extern "C" fn(NewAnyValue) -> Result, ()>, } impl ValueVTable { pub fn new>() -> Self { Self { get_value_vtable: T::get_value_vtable, deserialize: T::deserialize, serialize: T::serialize, } } } pub trait IntoValueVTable { unsafe extern "C" fn get_value_vtable() -> OperationVTable; unsafe extern "C" fn deserialize(src: &[u8]) -> Result; unsafe extern "C" fn serialize(this: NewAnyValue) -> Result, ()>; } impl IntoValueVTable for V where O: GiteratedObject, V: GiteratedObjectValue, { unsafe extern "C" fn get_value_vtable() -> OperationVTable { OperationVTable::new::() } unsafe extern "C" fn deserialize(src: &[u8]) -> Result { let _guard = trace_span!( "deserialize value", object = O::object_name(), value = V::value_name() ); trace!("Deserializing"); let deserialized: V = serde_json::from_slice(src).unwrap(); Ok(NewAnyValue { inner: FFIBox::from_box(Box::new(deserialized)).untyped(), vtable: ValueVTable::new::(), }) } unsafe extern "C" fn serialize(_this: NewAnyValue) -> Result, ()> { todo!() } }