use std::any::{type_name, TypeId};
use std::ops;
use parking_lot::{RwLockReadGuard, RwLockWriteGuard};
use crate::world::{self};
use crate::{comp, system, Archetype};
pub type ReadSimple<'t, A: Archetype, C: comp::Simple<A>> = system::AccessSingle<
A,
C,
impl ops::Deref<Target = <C as comp::SimpleOrIsotope<A>>::Storage> + 't,
>;
pub type WriteSimple<'t, A: Archetype, C: comp::Simple<A>> = system::AccessSingle<
A,
C,
impl ops::DerefMut<Target = <C as comp::SimpleOrIsotope<A>>::Storage> + 't,
>;
impl world::Components {
pub fn read_simple_storage<A: Archetype, C: comp::Simple<A>>(&self) -> ReadSimple<A, C> {
let storage = match self.archetype::<A>().simple_storages.get(&TypeId::of::<C>()) {
Some(storage) => storage,
None => panic!(
"The component {}/{} cannot be used because it is not used in any systems",
type_name::<A>(),
type_name::<C>()
),
};
let guard = match storage.storage.try_read() {
Some(guard) => guard,
None => panic!(
"The component {}/{} is currently exclusively locked by another system. Maybe \
scheduler bug?",
type_name::<A>(),
type_name::<C>()
),
};
let guard = RwLockReadGuard::map(guard, |storage| storage.downcast_ref::<C>());
system::AccessSingle::new(guard)
}
pub fn write_simple_storage<A: Archetype, C: comp::Simple<A>>(&self) -> WriteSimple<A, C> {
let storage = match self.archetype::<A>().simple_storages.get(&TypeId::of::<C>()) {
Some(storage) => storage,
None => panic!(
"The component {}/{} cannot be used because it is not used in any systems",
type_name::<A>(),
type_name::<C>()
),
};
let guard = match storage.storage.try_write() {
Some(guard) => guard,
None => panic!(
"The component {}/{} is currently used by another system. Maybe scheduler bug?",
type_name::<A>(),
type_name::<C>()
),
};
let guard = RwLockWriteGuard::map(guard, |storage| storage.downcast_mut::<C>());
system::AccessSingle::new(guard)
}
pub fn get_simple_storage<A: Archetype, C: comp::Simple<A>>(
&mut self,
) -> system::AccessSingle<A, C, &mut C::Storage> {
let typed = self.archetype_mut::<A>();
let storage = match typed.simple_storages.get_mut(&TypeId::of::<C>()) {
Some(storage) => storage,
None => panic!(
"The component {} cannot be retrieved because it is not used in any systems",
type_name::<C>()
),
};
let storage = storage.get_storage::<C>();
system::AccessSingle::new(storage)
}
}