use std::{ marker::PhantomData, mem::{transmute, MaybeUninit}, ptr::{null, null_mut, read}, }; use anyhow::Error; pub trait FromOperationState: Sized { fn from_operation_state( state: &mut State, object: &O, operation: &D, ) -> Result>; } pub struct StateExtractor(pub T); impl FromState for StateExtractor { fn from_state(state: &mut State) -> Result { todo!() } } use c_linked_list::CLinkedListMut; use giterated_models::{error::OperationError, value}; use crate::{ value_ex::FfiValueUntyped, vtable::{runtime::RuntimeHandle, VTable}, FfiValue, }; #[derive(Debug)] #[repr(transparent)] pub struct State { list: CLinkedListMut, fn(&StateItem<()>) -> *mut StateItem<()>>, } unsafe impl Send for State {} unsafe impl Sync for State {} impl Default for State { fn default() -> Self { let value = FfiValue::new(StateItem { next_item: core::ptr::null(), state_uuid: 0, state: (), }); State { list: unsafe { CLinkedListMut::from_ptr(value.ptr() as *const StateItem<()> as *mut _, |n| { n.next_item as *mut StateItem<()> }) }, } } } #[repr(transparent)] struct StateHandle { state: FfiValueUntyped, } impl StateHandle { pub unsafe fn clone_unsafe(&self) -> Self { Self { state: FfiValueUntyped { inner: self.state.inner, _type_marker: PhantomData, _abi_marker: PhantomData, }, } } } #[repr(C)] pub struct StateItem { /// The pointer to the next item. /// /// `next_item` is most likely always an `FfiValue>` and that's how we free them. next_item: *const StateItem<()>, pub state_uuid: u128, pub state: T, } impl std::fmt::Debug for StateItem { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("StateItem") .field("state_uuid", &self.state_uuid) .finish() } } impl Drop for State { fn drop(&mut self) { let state_manager = unsafe { StateManager::new(self) }; // for state in state_manager {} } } pub struct StateManager<'s, S> { state: S, _marker: PhantomData<&'s ()>, } impl<'s> StateManager<'s, &'s mut State> { pub unsafe fn new_mut(handle: &'s mut State) -> Self { Self { state: handle, _marker: PhantomData, } } pub unsafe fn write_state(&mut self, state: S) -> &mut Self { let list = &mut self.state.list; let last_item = list.iter_mut().last().unwrap(); last_item.next_item = unsafe { FfiValue::new(StateItem { next_item: null(), state_uuid: S::uuid(), state, }) .ptr() } as *const StateItem<()>; self } } impl<'s> StateManager<'s, &'s State> { pub unsafe fn new<'o: 's>(handle: &'o State) -> Self { Self { state: handle, _marker: PhantomData, } } pub unsafe fn get_state(&self) -> Option<&S> { println!("state info: {:#?}", self.state); for state in self.state.list.iter() { println!("iter"); if state.state_uuid == S::uuid() { let state: *const StateItem = unsafe { transmute(&state) }; let value_ref = state.as_ref().unwrap(); let value_ref = &value_ref.state as *const S; return value_ref.as_ref(); } } None } } pub trait StateUUID { fn uuid() -> u128; fn unsafe_hint_copy() -> Option { None } } /// State values for the current execution domain. 99.99% of the time this means "plugin-specific" /// /// The remainder 0.01% of the time it refers to the daemon's runtime domain. #[repr(transparent)] pub struct DomainState(pub &'static State); impl StateUUID for DomainState { fn uuid() -> u128 { 32894238940832489328402398490328423 } } pub struct RuntimeState(StateItem<&'static VTable>); impl StateUUID for RuntimeState { fn uuid() -> u128 { todo!() } } impl RuntimeState { pub fn queue_insert_state(&mut self, state: S) { todo!() } } pub trait FromState: Sized { fn from_state(state: &mut State) -> Result; } impl FromState for T { fn from_state(state: &mut State) -> Result { todo!() } } impl FromState for Option { fn from_state(state: &mut State) -> Result { todo!() } }