use crate::app_interface::TypeIdentifier; use alloc::rc::Rc; pub trait TypeLibraryTrait { fn get_type_from_name(&self, name: &str) -> Option; fn get_single_effectiveness( &self, attacking_type: TypeIdentifier, defending_type: TypeIdentifier, ) -> f32; fn get_effectiveness( &self, attacking_type: TypeIdentifier, defending_types: &[TypeIdentifier], ) -> f32; } pub type Typelibrary = Rc; #[cfg(not(feature = "mock_data"))] mod implementation { use super::*; use crate::handling::extern_ref::{ExternRef, ExternalReferenceType}; use alloc::rc::Rc; use alloc::string::{String, ToString}; use cstr_core::{c_char, CString}; use spin::RwLock; struct TypeLibraryInner { reference: ExternRef, name_to_type_cache: RwLock>, effectiveness_cache: RwLock>, } #[derive(Clone)] pub struct TypeLibraryImpl { inner: Rc, } impl TypeLibraryImpl { #[cfg(not(feature = "mock_data"))] pub(crate) fn new(reference: ExternRef) -> Self { Self { inner: Rc::new(TypeLibraryInner { reference, name_to_type_cache: Default::default(), effectiveness_cache: Default::default(), }), } } } impl TypeLibraryTrait for TypeLibraryImpl { fn get_type_from_name(&self, name: &str) -> Option { if let Some(cached) = self.inner.name_to_type_cache.read().get(name) { return Some(*cached); } let cstr = CString::new(name).unwrap(); let v = unsafe { type_library_get_type_by_name(self.inner.reference, cstr.as_ptr()) }; if v == 255 { return None; } let v = v.into(); self.inner .name_to_type_cache .write() .insert(name.to_string(), v); Some(v) } fn get_single_effectiveness( &self, attacking_type: TypeIdentifier, defending_type: TypeIdentifier, ) -> f32 { if let Some(cached) = self .inner .effectiveness_cache .read() .get(&(attacking_type, defending_type)) { return *cached; } let effectiveness = unsafe { type_library_get_single_effectiveness( self.inner.reference, attacking_type.into(), defending_type.into(), ) }; self.inner .effectiveness_cache .write() .insert((attacking_type, defending_type), effectiveness); effectiveness } fn get_effectiveness( &self, attacking_type: TypeIdentifier, defending_types: &[TypeIdentifier], ) -> f32 { let mut f = 1.0; for defending_type in defending_types { f *= self.get_single_effectiveness(attacking_type, *defending_type); } f } } crate::handling::cacheable::cacheable!(TypeLibraryImpl); #[cfg(not(feature = "mock_data"))] impl ExternalReferenceType for TypeLibraryImpl { fn from_extern_value(reference: ExternRef) -> Self { Self::new(reference) } } #[cfg(not(feature = "mock_data"))] extern "wasm" { fn type_library_get_single_effectiveness( r: ExternRef, attacking_type: u8, defending_type: u8, ) -> f32; fn type_library_get_type_by_name(r: ExternRef, name: *const c_char) -> u8; } } #[cfg(not(feature = "mock_data"))] pub use implementation::*;