Skip to content

Commit

Permalink
Add new resources and clean up component storages
Browse files Browse the repository at this point in the history
  • Loading branch information
LechintanTudor committed Jan 3, 2024
1 parent a736c5c commit 887d8c9
Show file tree
Hide file tree
Showing 15 changed files with 314 additions and 108 deletions.
1 change: 0 additions & 1 deletion .rustfmt.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
comment_width = 100
force_multiline_blocks = true
group_imports = "One"
imports_granularity = "Module"
max_width = 100
newline_style = "Unix"
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
pub mod components;
pub mod layout;
pub mod query;
pub mod resource;
pub mod resources;
pub mod storage;
pub mod systems;
Expand Down
10 changes: 5 additions & 5 deletions src/query/component_view.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::components::GroupInfo;
use crate::storage::{Component, Entity, SparseArray};
use crate::storage::{Component, Entity, SparseVec};
use crate::world::{Comp, CompMut};
use std::ops::RangeBounds;

Expand Down Expand Up @@ -36,7 +36,7 @@ pub trait ComponentView {
Self: 'a;

/// Splits the view for iteration.
fn split_for_iteration<'a>(self) -> (&'a [Entity], &'a SparseArray, Self::Ptr)
fn split_for_iteration<'a>(self) -> (&'a [Entity], &'a SparseVec, Self::Ptr)
where
Self: 'a;

Expand Down Expand Up @@ -100,7 +100,7 @@ where
Comp::group_info(self)
}

fn split_for_iteration<'a>(self) -> (&'a [Entity], &'a SparseArray, Self::Ptr)
fn split_for_iteration<'a>(self) -> (&'a [Entity], &'a SparseVec, Self::Ptr)
where
Self: 'a,
{
Expand Down Expand Up @@ -184,7 +184,7 @@ where
CompMut::group_info(self)
}

fn split_for_iteration<'a>(self) -> (&'a [Entity], &'a SparseArray, Self::Ptr)
fn split_for_iteration<'a>(self) -> (&'a [Entity], &'a SparseVec, Self::Ptr)
where
Self: 'a,
{
Expand Down Expand Up @@ -268,7 +268,7 @@ where
CompMut::group_info(self)
}

fn split_for_iteration<'a>(self) -> (&'a [Entity], &'a SparseArray, Self::Ptr)
fn split_for_iteration<'a>(self) -> (&'a [Entity], &'a SparseVec, Self::Ptr)
where
Self: 'a,
{
Expand Down
8 changes: 4 additions & 4 deletions src/query/query_part.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::query::{ComponentView, QueryGroupInfo};
use crate::storage::{Entity, SparseArray};
use crate::storage::{Entity, SparseVec};
use std::ops::RangeBounds;

/// Allows getting, including or excluding components in a query.
Expand Down Expand Up @@ -249,7 +249,7 @@ where
C: ComponentView,
{
type Refs<'a> = C::Ref<'a> where Self: 'a;
type Sparse<'a> = &'a SparseArray where Self: 'a;
type Sparse<'a> = &'a SparseVec where Self: 'a;
type Ptrs = C::Ptr;
type Slices<'a> = C::Slice<'a> where Self: 'a;

Expand Down Expand Up @@ -380,7 +380,7 @@ where
C: ComponentView,
{
type Refs<'a> = (C::Ref<'a>,) where Self: 'a;
type Sparse<'a> = (&'a SparseArray,) where Self: 'a;
type Sparse<'a> = (&'a SparseVec,) where Self: 'a;
type Ptrs = (C::Ptr,);
type Slices<'a> = (C::Slice<'a>,) where Self: 'a;

Expand Down Expand Up @@ -511,7 +511,7 @@ where

macro_rules! replace_with_sparse_array_ref {
($old:tt) => {
&'a SparseArray
&'a SparseVec
};
}

Expand Down
50 changes: 50 additions & 0 deletions src/resource/borrow.rs
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);
79 changes: 79 additions & 0 deletions src/resource/mod.rs
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()
}
}
105 changes: 105 additions & 0 deletions src/resource/storage.rs
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();
}
}
6 changes: 5 additions & 1 deletion src/resources/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ impl dyn Resource {
}

/// Tries to downcast `self` to a reference of type `T`.
#[must_use]
pub fn downcast_ref<T>(&self) -> Option<&T>
where
T: Resource,
Expand All @@ -55,13 +56,16 @@ impl dyn Resource {

/// Helper trait for implementing downcasting operations.
pub trait Downcast: 'static {
/// Returns `self` as a type-erases box.
/// 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;
}

Expand Down
Loading

0 comments on commit 887d8c9

Please sign in to comment.