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