Gen7ScriptsRs/pkmn_lib_interface/src/app_interface/static_data/data_libraries/mod.rs

226 lines
6.5 KiB
Rust
Executable File

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<StaticData>,
move_library: CachedValue<MoveLibrary>,
item_library: CachedValue<ItemLibrary>,
species_library: CachedValue<SpeciesLibrary>,
type_library: CachedValue<TypeLibrary>,
settings: CachedValue<LibrarySettings>,
}
#[derive(Clone)]
pub struct StaticData {
inner: Rc<StaticDataInner>,
}
impl StaticData {
#[cfg(not(feature = "mock_data"))]
pub(crate) fn new(reference: ExternRef<StaticData>) -> 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>) -> Self {
StaticData::new(reference)
}
}
struct LibrarySettingsInner {
maximum_level: CachedValue<LevelInt>,
}
#[derive(Clone)]
pub struct LibrarySettings {
inner: Rc<LibrarySettingsInner>,
}
impl LibrarySettings {
#[cfg(not(feature = "mock_data"))]
pub(crate) fn new(ptr: ExternRef<LibrarySettings>) -> 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>) -> Self {
LibrarySettings::new(reference)
}
}
#[cfg(not(feature = "mock_data"))]
extern "wasm" {
fn static_data_get_move_library(ptr: ExternRef<StaticData>) -> ExternRef<MoveLibrary>;
fn static_data_get_item_library(ptr: ExternRef<StaticData>) -> ExternRef<ItemLibrary>;
fn static_data_get_species_library(ptr: ExternRef<StaticData>) -> ExternRef<SpeciesLibrary>;
fn static_data_get_type_library(ptr: ExternRef<StaticData>) -> ExternRef<TypeLibrary>;
fn static_data_get_library_settings(ptr: ExternRef<StaticData>) -> ExternRef<LibrarySettings>;
fn library_settings_get_maximum_level(ptr: ExternRef<LibrarySettings>) -> LevelInt;
}
#[cfg(not(feature = "mock_data"))]
pub trait DataLibrary<T>: Cacheable
where
T: ExternalReferenceType,
T: Clone,
{
fn get_cache(&self) -> &RwLock<hashbrown::HashMap<u32, T>>;
fn get_self_ref(&self) -> ExternRef<Self>
where
Self: Sized;
fn _get_ref_by_name(ptr: ExternRef<Self>, name: ExternRef<StringKey>) -> ExternRef<T>
where
Self: Sized;
fn _get_ref_by_hash(ptr: ExternRef<Self>, hash: u32) -> ExternRef<T>
where
Self: Sized;
fn get(&self, name: &StringKey) -> Option<T>
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<T>
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<T>: Cacheable
where
T: Clone,
{
fn get_cache(&self) -> &RwLock<hashbrown::HashMap<u32, T>>;
fn get_self_ref(&self) -> ExternRef<Self>
where
Self: Sized;
fn get(&self, name: &StringKey) -> Option<T>
where
Self: Sized,
{
self.get_cache().read().get(&name.hash()).cloned()
}
fn get_by_hash(&self, hash: u32) -> Option<T>
where
Self: Sized,
{
self.get_cache().read().get(&hash).cloned()
}
fn insert(&self, hash: u32, item: T) {
self.get_cache().write().insert(hash, item);
}
}