use crate::{cached_value, cached_value_getters, ExternRef, ExternalReferenceType, StringKey}; use alloc::rc::Rc; use move_library::MoveLibrary; use spin::rwlock::RwLock; pub mod item_library; pub mod move_library; pub mod species_library; pub mod type_library; use crate::app_interface::species_library::SpeciesLibrary; use crate::app_interface::type_library::TypeLibrary; use crate::app_interface::LevelInt; use crate::handling::cached_value::CachedValue; use crate::handling::Cacheable; pub use item_library::*; pub use move_library::*; struct StaticDataInner { reference: ExternRef, move_library: CachedValue, item_library: CachedValue, species_library: CachedValue, type_library: CachedValue, settings: CachedValue, } #[derive(Clone)] pub struct StaticData { inner: Rc, } impl StaticData { #[cfg(not(feature = "mock_data"))] pub(crate) fn new(reference: ExternRef) -> Self { Self::from_ref(reference, &|reference| Self { inner: Rc::new(StaticDataInner { reference, move_library: cached_value!({ static_data_get_move_library(reference).get_value().unwrap() }), item_library: cached_value!({ static_data_get_item_library(reference).get_value().unwrap() }), species_library: cached_value!({ static_data_get_species_library(reference) .get_value() .unwrap() }), type_library: cached_value!({ static_data_get_type_library(reference).get_value().unwrap() }), settings: cached_value!({ static_data_get_library_settings(reference) .get_value() .unwrap() }), }), }) } #[cfg(feature = "mock_data")] pub fn mock( moves: MoveLibrary, items: ItemLibrary, species: SpeciesLibrary, types: TypeLibrary, settings: LibrarySettings, ) -> Self { Self { inner: Rc::new(StaticDataInner { reference: ExternRef::mock(), move_library: moves.into(), item_library: items.into(), species_library: species.into(), type_library: types.into(), settings: settings.into(), }), } } cached_value_getters! { pub fn move_library(&self) -> MoveLibrary; pub fn item_library(&self) -> ItemLibrary; pub fn species_library(&self) -> SpeciesLibrary; pub fn type_library(&self) -> TypeLibrary; } } crate::handling::cacheable::cacheable!(StaticData); #[cfg(not(feature = "mock_data"))] impl ExternalReferenceType for StaticData { fn from_extern_value(reference: ExternRef) -> Self { StaticData::new(reference) } } struct LibrarySettingsInner { maximum_level: CachedValue, } #[derive(Clone)] pub struct LibrarySettings { inner: Rc, } impl LibrarySettings { #[cfg(not(feature = "mock_data"))] pub(crate) fn new(ptr: ExternRef) -> Self { Self { inner: Rc::new(LibrarySettingsInner { maximum_level: cached_value!({ library_settings_get_maximum_level(ptr) }), }), } } #[cfg(feature = "mock_data")] pub fn mock(maximum_level: LevelInt) -> Self { Self { inner: Rc::new(LibrarySettingsInner { maximum_level: maximum_level.into(), }), } } cached_value_getters! { pub fn maximum_level(&self) -> LevelInt; } } #[cfg(not(feature = "mock_data"))] impl ExternalReferenceType for LibrarySettings { fn from_extern_value(reference: ExternRef) -> Self { LibrarySettings::new(reference) } } #[cfg(not(feature = "mock_data"))] extern "wasm" { fn static_data_get_move_library(ptr: ExternRef) -> ExternRef; fn static_data_get_item_library(ptr: ExternRef) -> ExternRef; fn static_data_get_species_library(ptr: ExternRef) -> ExternRef; fn static_data_get_type_library(ptr: ExternRef) -> ExternRef; fn static_data_get_library_settings(ptr: ExternRef) -> ExternRef; fn library_settings_get_maximum_level(ptr: ExternRef) -> LevelInt; } #[cfg(not(feature = "mock_data"))] pub trait DataLibrary: Cacheable where T: ExternalReferenceType, T: Clone, { fn get_cache(&self) -> &RwLock>; fn get_self_ref(&self) -> ExternRef where Self: Sized; fn _get_ref_by_name(ptr: ExternRef, name: ExternRef) -> ExternRef where Self: Sized; fn _get_ref_by_hash(ptr: ExternRef, hash: u32) -> ExternRef where Self: Sized; fn get(&self, name: &StringKey) -> Option where Self: Sized, { if let Some(v) = self.get_cache().read().get(&name.hash()) { return Some(v.clone()); } let v = Self::_get_ref_by_name(self.get_self_ref(), name.ptr()).get_value(); if let Some(v) = &v { self.get_cache().write().insert(name.hash(), v.clone()); } v } fn get_by_hash(&self, hash: u32) -> Option where Self: Sized, { if let Some(v) = self.get_cache().read().get(&hash) { return Some(v.clone()); } let v = Self::_get_ref_by_hash(self.get_self_ref(), hash).get_value(); if let Some(v) = &v { self.get_cache().write().insert(hash, v.clone()); } v } } #[cfg(feature = "mock_data")] pub trait DataLibrary: Cacheable where T: Clone, { fn get_cache(&self) -> &RwLock>; fn get_self_ref(&self) -> ExternRef where Self: Sized; fn get(&self, name: &StringKey) -> Option where Self: Sized, { self.get_cache().read().get(&name.hash()).cloned() } fn get_by_hash(&self, hash: u32) -> Option where Self: Sized, { self.get_cache().read().get(&hash).cloned() } fn insert(&self, hash: u32, item: T) { self.get_cache().write().insert(hash, item); } }