Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic maskedstorage #668

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions src/storage/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,18 @@ use crate::{
/// Note that you can also use `LazyUpdate` , which does insertions on
/// `World::maintain`. This allows more concurrency and is designed
/// to be used for entity initialization.
pub type ReadStorage<'a, T> = Storage<'a, T, Fetch<'a, MaskedStorage<T>>>;
#[allow(type_alias_bounds)]
pub type ReadStorage<'a, T: Component> = Storage<'a, T, Fetch<'a, MaskedStorage<T::Storage>>>;

impl<'a, T> SystemData<'a> for ReadStorage<'a, T>
where
T: Component,
{
fn setup(res: &mut World) {
res.entry::<MaskedStorage<T>>()
res.entry::<MaskedStorage<T::Storage>>()
.or_insert_with(|| MaskedStorage::new(<T::Storage as TryDefault>::unwrap_default()));
res.fetch_mut::<MetaTable<dyn AnyStorage>>()
.register(&*res.fetch::<MaskedStorage<T>>());
.register(&*res.fetch::<MaskedStorage<T::Storage>>());
}

fn fetch(res: &'a World) -> Self {
Expand All @@ -138,7 +139,7 @@ where
fn reads() -> Vec<ResourceId> {
vec![
ResourceId::new::<EntitiesRes>(),
ResourceId::new::<MaskedStorage<T>>(),
ResourceId::new::<MaskedStorage<T::Storage>>(),
]
}

Expand Down Expand Up @@ -209,17 +210,18 @@ where
///
/// There's also an Entry-API similar to the one provided by
/// `std::collections::HashMap`.
pub type WriteStorage<'a, T> = Storage<'a, T, FetchMut<'a, MaskedStorage<T>>>;
#[allow(type_alias_bounds)]
pub type WriteStorage<'a, T: Component> = Storage<'a, T, FetchMut<'a, MaskedStorage<T::Storage>>>;

impl<'a, T> SystemData<'a> for WriteStorage<'a, T>
where
T: Component,
{
fn setup(res: &mut World) {
res.entry::<MaskedStorage<T>>()
res.entry::<MaskedStorage<T::Storage>>()
.or_insert_with(|| MaskedStorage::new(<T::Storage as TryDefault>::unwrap_default()));
res.fetch_mut::<MetaTable<dyn AnyStorage>>()
.register(&*res.fetch::<MaskedStorage<T>>());
.register(&*res.fetch::<MaskedStorage<T::Storage>>());
}

fn fetch(res: &'a World) -> Self {
Expand All @@ -231,7 +233,7 @@ where
}

fn writes() -> Vec<ResourceId> {
vec![ResourceId::new::<MaskedStorage<T>>()]
vec![ResourceId::new::<MaskedStorage<T::Storage>>()]
}
}

Expand Down Expand Up @@ -259,10 +261,10 @@ mod tests {

let mut d = DispatcherBuilder::new().with(Sys, "sys", &[]).build();

assert!(!w.has_value::<MaskedStorage<Foo>>());
assert!(!w.has_value::<MaskedStorage<<Foo as Component>::Storage>>());

d.setup(&mut w);

assert!(w.has_value::<MaskedStorage<Foo>>());
assert!(w.has_value::<MaskedStorage<<Foo as Component>::Storage>>());
}
}
4 changes: 2 additions & 2 deletions src/storage/drain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
/// that removes the components.
pub struct Drain<'a, T: Component> {
/// The masked storage
pub data: &'a mut MaskedStorage<T>,
pub data: &'a mut MaskedStorage<T::Storage>,
}

impl<'a, T> Join for Drain<'a, T>
Expand All @@ -19,7 +19,7 @@ where
{
type Mask = BitSet;
type Type = T;
type Value = &'a mut MaskedStorage<T>;
type Value = &'a mut MaskedStorage<T::Storage>;

// SAFETY: No invariants to meet and no unsafe code.
unsafe fn open(self) -> (Self::Mask, Self::Value) {
Expand Down
14 changes: 7 additions & 7 deletions src/storage/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::join::Join;
impl<'e, T, D> Storage<'e, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
D: DerefMut<Target = MaskedStorage<T::Storage>>,
{
/// Returns an entry to the component associated to the entity.
///
Expand Down Expand Up @@ -110,7 +110,7 @@ where
/// for (mut counter, _) in (counters.entries(), &marker).join() {
/// let counter = counter.or_insert_with(Default::default);
/// counter.increase();
///
///
/// if counter.reached_limit() {
/// counter.reset();
/// // Do something
Expand All @@ -130,7 +130,7 @@ pub struct Entries<'a, 'b: 'a, T: 'a, D: 'a>(&'a mut Storage<'b, T, D>);
impl<'a, 'b: 'a, T: 'a, D: 'a> Join for Entries<'a, 'b, T, D>
where
T: Component,
D: Deref<Target = MaskedStorage<T>>,
D: Deref<Target = MaskedStorage<T::Storage>>,
{
type Mask = BitSetAll;
type Type = StorageEntry<'a, 'b, T, D>;
Expand Down Expand Up @@ -175,7 +175,7 @@ pub struct OccupiedEntry<'a, 'b: 'a, T: 'a, D: 'a> {
impl<'a, 'b, T, D> OccupiedEntry<'a, 'b, T, D>
where
T: Component,
D: Deref<Target = MaskedStorage<T>>,
D: Deref<Target = MaskedStorage<T::Storage>>,
{
/// Get a reference to the component associated with the entity.
pub fn get(&self) -> &T {
Expand All @@ -188,7 +188,7 @@ where
impl<'a, 'b, T, D> OccupiedEntry<'a, 'b, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
D: DerefMut<Target = MaskedStorage<T::Storage>>,
{
/// Get a mutable reference to the component associated with the entity.
pub fn get_mut(&mut self) -> &mut T {
Expand Down Expand Up @@ -227,7 +227,7 @@ pub struct VacantEntry<'a, 'b: 'a, T: 'a, D: 'a> {
impl<'a, 'b, T, D> VacantEntry<'a, 'b, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
D: DerefMut<Target = MaskedStorage<T::Storage>>,
{
/// Inserts a value into the storage.
pub fn insert(self, component: T) -> &'a mut T {
Expand All @@ -252,7 +252,7 @@ pub enum StorageEntry<'a, 'b: 'a, T: 'a, D: 'a> {
impl<'a, 'b, T, D> StorageEntry<'a, 'b, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
D: DerefMut<Target = MaskedStorage<T::Storage>>,
{
/// Inserts a component if the entity does not have it already.
pub fn or_insert(self, component: T) -> &'a mut T {
Expand Down
4 changes: 3 additions & 1 deletion src/storage/flagged.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,9 @@ where
}
}

impl<C: Component, T: UnprotectedStorage<C>> UnprotectedStorage<C> for FlaggedStorage<C, T> {
impl<C: Component, T: UnprotectedStorage<Item = C>> UnprotectedStorage for FlaggedStorage<C, T> {
type Item = C;

unsafe fn clean<B>(&mut self, has: B)
where
B: BitSetLike,
Expand Down
76 changes: 50 additions & 26 deletions src/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,7 @@ where
}
}

impl<T> AnyStorage for MaskedStorage<T>
where
T: Component,
{
impl<S: UnprotectedStorage> AnyStorage for MaskedStorage<S> {
fn drop(&mut self, entities: &[Entity]) {
for entity in entities {
MaskedStorage::drop(self, entity.id());
Expand Down Expand Up @@ -131,23 +128,23 @@ pub type InsertResult<T> = Result<Option<T>, Error>;
/// The `UnprotectedStorage` together with the `BitSet` that knows
/// about which elements are stored, and which are not.
#[derive(Derivative)]
#[derivative(Default(bound = "T::Storage: Default"))]
pub struct MaskedStorage<T: Component> {
#[derivative(Default(bound = "S: Default"))]
pub struct MaskedStorage<S: UnprotectedStorage> {
mask: BitSet,
inner: T::Storage,
inner: S,
}

impl<T: Component> MaskedStorage<T> {
impl<S: UnprotectedStorage> MaskedStorage<S> {
/// Creates a new `MaskedStorage`. This is called when you register
/// a new component type within the world.
pub fn new(inner: T::Storage) -> MaskedStorage<T> {
pub fn new(inner: S) -> MaskedStorage<S> {
MaskedStorage {
mask: BitSet::new(),
inner,
}
}

fn open_mut(&mut self) -> (&BitSet, &mut T::Storage) {
fn open_mut(&mut self) -> (&BitSet, &mut S) {
(&self.mask, &mut self.inner)
}

Expand All @@ -160,8 +157,33 @@ impl<T: Component> MaskedStorage<T> {
self.mask.clear();
}

/// Check if the given id refers to a valid element in the storage.
pub fn contains(&self, id: Index) -> bool {
self.mask.contains(id)
}

/// Get an element by a given index.
pub fn get(&self, id: Index) -> Option<&S::Item> {
if self.mask.contains(id) {
// SAFETY: We checked the mask (`contains` returned `true`)
Some(unsafe { self.inner.get(id) })
} else {
None
}
}

/// Get an element mutably by a given index.
pub fn get_mut(&mut self, id: Index) -> Option<&mut S::Item> {
if self.mask.contains(id) {
// SAFETY: We checked the mask (`contains` returned `true`)
Some(unsafe { self.inner.get_mut(id) })
} else {
None
}
}

/// Remove an element by a given index.
pub fn remove(&mut self, id: Index) -> Option<T> {
pub fn remove(&mut self, id: Index) -> Option<S::Item> {
if self.mask.remove(id) {
// SAFETY: We checked the mask (`remove` returned `true`)
Some(unsafe { self.inner.remove(id) })
Expand All @@ -181,7 +203,7 @@ impl<T: Component> MaskedStorage<T> {
}
}

impl<T: Component> Drop for MaskedStorage<T> {
impl<S: UnprotectedStorage> Drop for MaskedStorage<S> {
fn drop(&mut self) {
self.clear();
}
Expand Down Expand Up @@ -211,7 +233,7 @@ impl<'e, T, D> Storage<'e, T, D> {
impl<'e, T, D> Storage<'e, T, D>
where
T: Component,
D: Deref<Target = MaskedStorage<T>>,
D: Deref<Target = MaskedStorage<T::Storage>>,
{
/// Gets the wrapped storage.
pub fn unprotected_storage(&self) -> &T::Storage {
Expand Down Expand Up @@ -264,7 +286,7 @@ where
impl<'e, T, D> Storage<'e, T, D>
where
T: Component,
D: Deref<Target = MaskedStorage<T>>,
D: Deref<Target = MaskedStorage<T::Storage>>,
T::Storage: SliceAccess<T>
{
/// Returns the component data as a slice.
Expand All @@ -279,7 +301,7 @@ impl<'e, T, D> Storage<'e, T, D>
impl<'e, T, D> Storage<'e, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
D: DerefMut<Target = MaskedStorage<T::Storage>>,
T::Storage: SliceAccess<T>
{
/// Returns the component data as a slice.
Expand All @@ -294,7 +316,7 @@ impl<'e, T, D> Storage<'e, T, D>
impl<'e, T, D> Storage<'e, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
D: DerefMut<Target = MaskedStorage<T::Storage>>,
{
/// Gets mutable access to the wrapped storage.
///
Expand Down Expand Up @@ -378,7 +400,7 @@ unsafe impl<'a, T: Component, D> DistinctStorage for Storage<'a, T, D> where
impl<'a, 'e, T, D> Join for &'a Storage<'e, T, D>
where
T: Component,
D: Deref<Target = MaskedStorage<T>>,
D: Deref<Target = MaskedStorage<T::Storage>>,
{
type Mask = &'a BitSet;
type Type = &'a T;
Expand All @@ -399,7 +421,7 @@ where
impl<'a, 'e, T, D> Not for &'a Storage<'e, T, D>
where
T: Component,
D: Deref<Target = MaskedStorage<T>>,
D: Deref<Target = MaskedStorage<T::Storage>>,
{
type Output = AntiStorage<'a>;

Expand All @@ -414,15 +436,15 @@ where
unsafe impl<'a, 'e, T, D> ParJoin for &'a Storage<'e, T, D>
where
T: Component,
D: Deref<Target = MaskedStorage<T>>,
D: Deref<Target = MaskedStorage<T::Storage>>,
T::Storage: Sync,
{
}

impl<'a, 'e, T, D> Join for &'a mut Storage<'e, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
D: DerefMut<Target = MaskedStorage<T::Storage>>,
{
type Mask = &'a BitSet;
type Type = &'a mut T;
Expand All @@ -448,7 +470,7 @@ where
unsafe impl<'a, 'e, T, D> ParJoin for &'a mut Storage<'e, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
D: DerefMut<Target = MaskedStorage<T::Storage>>,
T::Storage: Sync + DistinctStorage,
{
}
Expand Down Expand Up @@ -478,7 +500,9 @@ where
}

/// Used by the framework to quickly join components.
pub trait UnprotectedStorage<T>: TryDefault {
pub trait UnprotectedStorage: TryDefault {
/// The item that is stored.
type Item;
/// Clean the storage given a bitset with bits set for valid indices.
/// Allows us to safely drop the storage.
///
Expand All @@ -501,7 +525,7 @@ pub trait UnprotectedStorage<T>: TryDefault {
///
/// A mask should keep track of those states, and an `id` being contained
/// in the tracking mask is sufficient to call this method.
unsafe fn get(&self, id: Index) -> &T;
unsafe fn get(&self, id: Index) -> &Self::Item;

/// Tries mutating the data associated with an `Index`.
/// This is unsafe because the external set used
Expand All @@ -514,7 +538,7 @@ pub trait UnprotectedStorage<T>: TryDefault {
///
/// A mask should keep track of those states, and an `id` being contained
/// in the tracking mask is sufficient to call this method.
unsafe fn get_mut(&mut self, id: Index) -> &mut T;
unsafe fn get_mut(&mut self, id: Index) -> &mut Self::Item;

/// Inserts new data for a given `Index`.
///
Expand All @@ -525,15 +549,15 @@ pub trait UnprotectedStorage<T>: TryDefault {
///
/// A mask should keep track of those states, and an `id` missing from the
/// mask is sufficient to call `insert`.
unsafe fn insert(&mut self, id: Index, value: T);
unsafe fn insert(&mut self, id: Index, value: Self::Item);

/// Removes the data associated with an `Index`.
///
/// # Safety
///
/// May only be called if an element with `id` was `insert`ed and not yet
/// removed / dropped.
unsafe fn remove(&mut self, id: Index) -> T;
unsafe fn remove(&mut self, id: Index) -> Self::Item;

/// Drops the data associated with an `Index`.
/// This is simply more efficient than `remove` and can be used if the data
Expand Down
4 changes: 2 additions & 2 deletions src/storage/restrict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ where
impl<'st, T, D> Storage<'st, T, D>
where
T: Component,
D: Deref<Target = MaskedStorage<T>>,
D: Deref<Target = MaskedStorage<T::Storage>>,
{
/// Builds an immutable `RestrictedStorage` out of a `Storage`. Allows
/// deferred unchecked access to the entity's component.
Expand All @@ -184,7 +184,7 @@ where
impl<'st, T, D> Storage<'st, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
D: DerefMut<Target = MaskedStorage<T::Storage>>,
{
/// Builds a mutable `RestrictedStorage` out of a `Storage`. Allows
/// restricted access to the inner components without allowing
Expand Down
Loading