-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new resources and clean up component storages
- Loading branch information
1 parent
a736c5c
commit 887d8c9
Showing
15 changed files
with
314 additions
and
108 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
use atomic_refcell::{AtomicRef, AtomicRefMut}; | ||
use std::fmt; | ||
use std::ops::{Deref, DerefMut}; | ||
|
||
pub struct Res<'a, T>(pub(crate) AtomicRef<'a, T>); | ||
|
||
pub struct ResMut<'a, T>(pub(crate) AtomicRefMut<'a, T>); | ||
|
||
impl<T> DerefMut for ResMut<'_, T> { | ||
#[inline] | ||
fn deref_mut(&mut self) -> &mut Self::Target { | ||
&mut self.0 | ||
} | ||
} | ||
|
||
macro_rules! impl_res_common { | ||
($Res:ident) => { | ||
impl<T> Deref for $Res<'_, T> { | ||
type Target = T; | ||
|
||
#[must_use] | ||
fn deref(&self) -> &T { | ||
&self.0 | ||
} | ||
} | ||
|
||
impl<T> fmt::Debug for $Res<'_, T> | ||
where | ||
T: fmt::Debug, | ||
{ | ||
#[inline] | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
self.0.fmt(f) | ||
} | ||
} | ||
|
||
impl<T> fmt::Display for $Res<'_, T> | ||
where | ||
T: fmt::Display, | ||
{ | ||
#[inline] | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
self.0.fmt(f) | ||
} | ||
} | ||
}; | ||
} | ||
|
||
impl_res_common!(Res); | ||
impl_res_common!(ResMut); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
mod borrow; | ||
mod storage; | ||
|
||
pub use self::borrow::*; | ||
pub use self::storage::*; | ||
|
||
use std::any::Any; | ||
|
||
pub trait Resource: Send + Sync + 'static { | ||
/// Returns `self` as a type-erased box. | ||
#[must_use] | ||
fn into_any(self: Box<Self>) -> Box<dyn Any>; | ||
|
||
/// Returns `self` as a type-erased reference. | ||
#[must_use] | ||
fn as_any(&self) -> &dyn Any; | ||
|
||
/// Returns `self` as a type-erased mutable reference. | ||
#[must_use] | ||
fn as_any_mut(&mut self) -> &mut dyn Any; | ||
} | ||
|
||
impl<T> Resource for T | ||
where | ||
T: Send + Sync + 'static, | ||
{ | ||
fn into_any(self: Box<Self>) -> Box<dyn Any> { | ||
self | ||
} | ||
|
||
fn as_any(&self) -> &dyn Any { | ||
self | ||
} | ||
|
||
fn as_any_mut(&mut self) -> &mut dyn Any { | ||
self | ||
} | ||
} | ||
|
||
impl dyn Resource { | ||
/// Returns whether the resource is of type `T`. | ||
#[must_use] | ||
pub fn is<T>(&self) -> bool | ||
where | ||
T: Resource, | ||
{ | ||
self.as_any().is::<T>() | ||
} | ||
|
||
/// Tries to downcast `self` to a box of type `T`. If the conversion fails, the original box is | ||
/// returned. | ||
pub fn downcast<T>(self: Box<Self>) -> Result<Box<T>, Box<Self>> | ||
where | ||
T: Resource, | ||
{ | ||
if self.is::<T>() { | ||
Ok(self.into_any().downcast().unwrap()) | ||
} else { | ||
Err(self) | ||
} | ||
} | ||
|
||
/// Tries to downcast `self` to a reference of type `T`. | ||
#[must_use] | ||
pub fn downcast_ref<T>(&self) -> Option<&T> | ||
where | ||
T: Resource, | ||
{ | ||
self.as_any().downcast_ref() | ||
} | ||
|
||
/// Tries to downcast `self` to a mutable reference of type `T`. | ||
pub fn downcast_mut<T>(&mut self) -> Option<&mut T> | ||
where | ||
T: Resource, | ||
{ | ||
self.as_any_mut().downcast_mut() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
use crate::resource::{Res, ResMut, Resource}; | ||
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; | ||
use rustc_hash::FxHashMap; | ||
use std::any::TypeId; | ||
use std::collections::hash_map::Entry; | ||
use std::mem; | ||
|
||
#[derive(Default)] | ||
pub struct ResourceStorage { | ||
resources: FxHashMap<TypeId, AtomicRefCell<Box<dyn Resource>>>, | ||
} | ||
|
||
impl ResourceStorage { | ||
pub fn insert<T>(&mut self, resource: T) -> Option<T> | ||
where | ||
T: Resource, | ||
{ | ||
match self.resources.entry(TypeId::of::<T>()) { | ||
Entry::Vacant(entry) => { | ||
entry.insert(AtomicRefCell::new(Box::new(resource))); | ||
None | ||
} | ||
Entry::Occupied(mut entry) => { | ||
let old_resource = unsafe { | ||
entry | ||
.get_mut() | ||
.get_mut() | ||
.as_mut() | ||
.downcast_mut::<T>() | ||
.unwrap_unchecked() | ||
}; | ||
|
||
Some(mem::replace(old_resource, resource)) | ||
} | ||
} | ||
} | ||
|
||
pub fn remove<T>(&mut self) -> Option<T> | ||
where | ||
T: Resource, | ||
{ | ||
self.resources | ||
.remove(&TypeId::of::<T>()) | ||
.map(|cell| unsafe { *cell.into_inner().downcast().unwrap_unchecked() }) | ||
} | ||
|
||
#[must_use] | ||
pub fn contains<T>(&self) -> bool | ||
where | ||
T: Resource, | ||
{ | ||
self.resources.contains_key(&TypeId::of::<T>()) | ||
} | ||
|
||
#[must_use] | ||
pub fn get_mut<T>(&mut self) -> Option<&mut T> | ||
where | ||
T: Resource, | ||
{ | ||
self.resources | ||
.get_mut(&TypeId::of::<T>()) | ||
.map(|cell| unsafe { cell.get_mut().downcast_mut().unwrap_unchecked() }) | ||
} | ||
|
||
#[inline] | ||
pub fn borrow<T>(&self) -> Option<Res<T>> | ||
where | ||
T: Resource, | ||
{ | ||
self.resources.get(&TypeId::of::<T>()).map(|cell| { | ||
Res(AtomicRef::map(cell.borrow(), |cell| unsafe { | ||
cell.downcast_ref().unwrap_unchecked() | ||
})) | ||
}) | ||
} | ||
|
||
#[inline] | ||
pub fn borrow_mut<T>(&self) -> Option<ResMut<T>> | ||
where | ||
T: Resource, | ||
{ | ||
self.resources.get(&TypeId::of::<T>()).map(|cell| { | ||
ResMut(AtomicRefMut::map(cell.borrow_mut(), |cell| unsafe { | ||
cell.downcast_mut().unwrap_unchecked() | ||
})) | ||
}) | ||
} | ||
|
||
#[inline] | ||
#[must_use] | ||
pub fn is_empty(&self) -> bool { | ||
self.resources.is_empty() | ||
} | ||
|
||
#[inline] | ||
#[must_use] | ||
pub fn len(&self) -> usize { | ||
self.resources.len() | ||
} | ||
|
||
#[inline] | ||
pub fn clear(&mut self) { | ||
self.resources.clear(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.