use core::slice::SliceIndex; use crate::check_global_threading_available; trait StoreBackend { fn free_slot(&mut self, length: usize) -> Option<*mut [u8]>; } struct Store<'a> { mutex: crate::fsrc::mutex::RawMutex, backend: &'a mut dyn StoreBackend, } impl<'a> Store<'a> { pub fn accessor(&mut self) -> StoreAccessor { check_global_threading_available!(); // holy shit, this is really unsafe, even for us: // we cast away the lifetime // this is safe as we only do it in threading // and the Accessor will only use it while still in threading // (the accessor is a smart pointer refusing to be smart outside // of threading) let static_pointer = unsafe { core::mem::transmute::<*mut Store<'a>, *mut Store<'static>>(self) }; StoreAccessor { store: static_pointer, } } fn free_slot(&mut self, length: usize) -> Result { if let Ok(_guard) = self.mutex.take() { if let Some(data) = self.backend.free_slot(length){ Ok(StoreSlot { data: data }) } else { Err(()) } } else { Err(()) } } } // TODO needs to be able to be uninitialized as it should be usable as member // A smart pointer to a Store protecting insane (static) pointer usage // only works during threading, panics otherwise struct StoreAccessor { store: *mut Store<'static>, } impl StoreAccessor { fn free_slot(&self, length: usize) -> Result { check_global_threading_available!(); unsafe { (*self.store).free_slot(length) } } } struct StoreSlot { data: *mut [u8], } impl StoreSlot { pub fn get(&self, index: I) -> &mut [u8] where I: SliceIndex { check_global_threading_available!(); unsafe { &mut (*self.data) } } pub fn get_all(&self) -> &mut [u8] { check_global_threading_available!(); unsafe { &mut (*self.data) } } }