Gen7ScriptsRs/pkmn_lib_interface/src/handling/temporary.rs

107 lines
2.6 KiB
Rust
Executable File

use alloc::rc::Rc;
use core::sync::atomic::{AtomicBool, Ordering};
#[cfg(not(feature = "mock_data"))]
pub struct Temporary<T> {
is_deleted: Rc<AtomicBool>,
value: Rc<T>,
}
#[cfg(not(feature = "mock_data"))]
static mut TEMPORARIES: Option<hashbrown::HashMap<u32, Rc<AtomicBool>>> = None;
#[cfg(not(feature = "mock_data"))]
impl<T> Temporary<T> {
#[inline]
pub fn new(reference: u32, value: T) -> Self {
unsafe {
if let None = TEMPORARIES {
TEMPORARIES = Some(hashbrown::HashMap::new());
}
}
let temporaries = unsafe { &mut TEMPORARIES }.as_mut().unwrap();
let existing = temporaries.get(&reference);
if let Some(v) = existing {
return Self {
is_deleted: v.clone(),
value: Rc::new(value),
};
}
let value = Rc::new(value);
let is_deleted = Rc::new(AtomicBool::new(false));
temporaries.insert(reference, is_deleted.clone());
Self { is_deleted, value }
}
#[inline]
pub fn value(&self) -> Rc<T> {
if self.is_deleted.load(Ordering::SeqCst) {
panic!("Accessed value after it had been deleted");
}
self.value.clone()
}
#[inline]
pub fn value_ref(&self) -> &T {
if self.is_deleted.load(Ordering::SeqCst) {
panic!("Accessed value after it had been deleted");
}
self.value.as_ref()
}
}
#[cfg(not(feature = "mock_data"))]
impl Temporary<u8> {
pub(crate) fn mark_as_deleted(reference: u32) {
let temporaries = unsafe { &mut TEMPORARIES };
let existing = temporaries.as_mut().unwrap().get_mut(&reference);
if let Some(v) = existing {
v.store(false, Ordering::SeqCst);
}
}
}
#[cfg(not(feature = "mock_data"))]
impl<T> Clone for Temporary<T> {
fn clone(&self) -> Self {
Self {
is_deleted: self.is_deleted.clone(),
value: self.value.clone(),
}
}
}
#[no_mangle]
#[cfg(not(feature = "mock_data"))]
unsafe extern "wasm" fn _mark_deleted(r: u32) {
Temporary::<u8>::mark_as_deleted(r)
}
#[cfg(feature = "mock_data")]
pub struct Temporary<T> {
value: Rc<T>,
}
#[cfg(feature = "mock_data")]
impl<T> Temporary<T> {
#[inline]
pub fn value(&self) -> Rc<T> {
self.value.clone()
}
#[inline]
pub fn value_ref(&self) -> &T {
&self.value
}
}
#[cfg(feature = "mock_data")]
impl<T> Clone for Temporary<T> {
fn clone(&self) -> Self {
Self {
value: self.value.clone(),
}
}
}