Files
obsw/mission_rust/src/fsrc/store.rs

73 lines
2.0 KiB
Rust

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<StoreSlot, ()> {
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<StoreSlot, ()> {
check_global_threading_available!();
unsafe { (*self.store).free_slot(length) }
}
}
struct StoreSlot {
data: *mut [u8],
}
impl StoreSlot {
pub fn get<I>(&self, index: I) -> &mut [u8]
where I: SliceIndex<u8>
{
check_global_threading_available!();
unsafe { &mut (*self.data) }
}
pub fn get_all(&self) -> &mut [u8] {
check_global_threading_available!();
unsafe { &mut (*self.data) }
}
}