-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
These views can initialize unique components Related issue: #209
- Loading branch information
Showing
7 changed files
with
558 additions
and
2 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
use crate::all_storages::AllStorages; | ||
use crate::atomic_refcell::ARef; | ||
use crate::borrow::{Borrow, WorldBorrow}; | ||
use crate::component::Unique; | ||
use crate::info::TypeInfo; | ||
use crate::tracking::TrackingTimestamp; | ||
use crate::views::UniqueView; | ||
use crate::world::World; | ||
use crate::{error, BorrowInfo}; | ||
use std::ops::Deref; | ||
|
||
/// Shared view over a unique component storage. | ||
/// | ||
/// If the component is not already present, its default value will be inserted. | ||
pub struct UniqueOrDefaultView<'v, T: Unique + Default>(UniqueView<'v, T>); | ||
|
||
impl<'v, T: Unique + Default> Deref for UniqueOrDefaultView<'v, T> { | ||
type Target = T; | ||
|
||
fn deref(&self) -> &Self::Target { | ||
&self.0 | ||
} | ||
} | ||
|
||
impl<'v, T: Unique + Default + Send + Sync> WorldBorrow for UniqueOrDefaultView<'v, T> { | ||
type WorldView<'a> = UniqueOrDefaultView<'a, T>; | ||
|
||
fn world_borrow( | ||
world: &World, | ||
last_run: Option<TrackingTimestamp>, | ||
current: TrackingTimestamp, | ||
) -> Result<Self::WorldView<'_>, error::GetStorage> { | ||
let all_storages = world | ||
.all_storages() | ||
.map_err(error::GetStorage::AllStoragesBorrow)?; | ||
|
||
match all_storages.borrow::<UniqueView<'_, T>>() { | ||
Ok(_) => {} | ||
Err(error::GetStorage::MissingStorage { .. }) => all_storages.add_unique(T::default()), | ||
Err(err) => return Err(err), | ||
}; | ||
|
||
let (all_storages, all_borrow) = unsafe { ARef::destructure(all_storages) }; | ||
|
||
let view = UniqueView::borrow(all_storages, Some(all_borrow), last_run, current)?; | ||
|
||
Ok(UniqueOrDefaultView(view)) | ||
} | ||
} | ||
|
||
unsafe impl<'v, T: Unique + Default + Send + Sync> BorrowInfo for UniqueOrDefaultView<'v, T> { | ||
fn borrow_info(info: &mut Vec<TypeInfo>) { | ||
UniqueView::<T>::borrow_info(info); | ||
} | ||
|
||
fn enable_tracking( | ||
enable_tracking_fn: &mut Vec<fn(&AllStorages) -> Result<(), error::GetStorage>>, | ||
) { | ||
UniqueView::<T>::enable_tracking(enable_tracking_fn); | ||
} | ||
} |
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,67 @@ | ||
use crate::all_storages::AllStorages; | ||
use crate::atomic_refcell::ARef; | ||
use crate::borrow::{Borrow, WorldBorrow}; | ||
use crate::component::Unique; | ||
use crate::info::TypeInfo; | ||
use crate::tracking::TrackingTimestamp; | ||
use crate::views::UniqueViewMut; | ||
use crate::world::World; | ||
use crate::{error, BorrowInfo}; | ||
use std::ops::{Deref, DerefMut}; | ||
|
||
/// Exclusive view over a unique component storage. | ||
/// | ||
/// If the component is not already present, its default value will be inserted. | ||
pub struct UniqueOrDefaultViewMut<'v, T: Unique + Default>(UniqueViewMut<'v, T>); | ||
|
||
impl<'v, T: Unique + Default> Deref for UniqueOrDefaultViewMut<'v, T> { | ||
type Target = T; | ||
|
||
fn deref(&self) -> &Self::Target { | ||
&self.0 | ||
} | ||
} | ||
|
||
impl<'v, T: Unique + Default> DerefMut for UniqueOrDefaultViewMut<'v, T> { | ||
fn deref_mut(&mut self) -> &mut Self::Target { | ||
&mut self.0 | ||
} | ||
} | ||
|
||
impl<'v, T: Unique + Default + Send + Sync> WorldBorrow for UniqueOrDefaultViewMut<'v, T> { | ||
type WorldView<'a> = UniqueOrDefaultViewMut<'a, T>; | ||
|
||
fn world_borrow( | ||
world: &World, | ||
last_run: Option<TrackingTimestamp>, | ||
current: TrackingTimestamp, | ||
) -> Result<Self::WorldView<'_>, error::GetStorage> { | ||
let all_storages = world | ||
.all_storages() | ||
.map_err(error::GetStorage::AllStoragesBorrow)?; | ||
|
||
match all_storages.borrow::<UniqueViewMut<'_, T>>() { | ||
Ok(_) => {} | ||
Err(error::GetStorage::MissingStorage { .. }) => all_storages.add_unique(T::default()), | ||
Err(err) => return Err(err), | ||
}; | ||
|
||
let (all_storages, all_borrow) = unsafe { ARef::destructure(all_storages) }; | ||
|
||
let view = UniqueViewMut::borrow(all_storages, Some(all_borrow), last_run, current)?; | ||
|
||
Ok(UniqueOrDefaultViewMut(view)) | ||
} | ||
} | ||
|
||
unsafe impl<'v, T: Unique + Default + Send + Sync> BorrowInfo for UniqueOrDefaultViewMut<'v, T> { | ||
fn borrow_info(info: &mut Vec<TypeInfo>) { | ||
UniqueViewMut::<T>::borrow_info(info); | ||
} | ||
|
||
fn enable_tracking( | ||
enable_tracking_fn: &mut Vec<fn(&AllStorages) -> Result<(), error::GetStorage>>, | ||
) { | ||
UniqueViewMut::<T>::enable_tracking(enable_tracking_fn); | ||
} | ||
} |
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,181 @@ | ||
use crate::all_storages::AllStorages; | ||
use crate::atomic_refcell::{ARef, SharedBorrow}; | ||
use crate::borrow::{Borrow, BorrowInfo, WorldBorrow}; | ||
use crate::component::Unique; | ||
use crate::error; | ||
use crate::info::TypeInfo; | ||
use crate::tracking::TrackingTimestamp; | ||
use crate::views::UniqueView; | ||
use crate::world::World; | ||
use core::cell::OnceCell; | ||
|
||
/// Shared view over a unique component storage. | ||
/// | ||
/// The component can be initialized with this view. | ||
pub struct UniqueOrInitView<'v, T: Unique + Default> { | ||
cell: OnceCell<UniqueView<'v, T>>, | ||
all_storages: &'v AllStorages, | ||
all_borrow: SharedBorrow<'v>, | ||
last_run: Option<TrackingTimestamp>, | ||
current: TrackingTimestamp, | ||
} | ||
|
||
impl<'v, T: Unique + Default + Send + Sync> UniqueOrInitView<'v, T> { | ||
/// Gets a reference to the inner [`UniqueView`]. | ||
/// | ||
/// Returns `None` if this view doesn't contains the inner [`UniqueView`]. | ||
pub fn get(&self) -> Option<&UniqueView<'v, T>> { | ||
self.cell.get() | ||
} | ||
|
||
/// Adds the unique component to the `World`. | ||
/// | ||
/// Returns `true` if the component was inserted. | ||
/// | ||
/// ### Borrows | ||
/// | ||
/// - `Unique<T>` storage (shared) | ||
/// | ||
/// ### Errors | ||
/// | ||
/// - `Unique<T>` storage borrow failed (it can be initialized and borrowed elsewhere). | ||
pub fn set(&self, unique: T) -> Result<bool, error::GetStorage> { | ||
if self.cell.get().is_some() { | ||
return Ok(false); | ||
} | ||
|
||
self.all_storages.add_unique(unique); | ||
|
||
self.cell | ||
.set(UniqueView::borrow( | ||
self.all_storages, | ||
Some(self.all_borrow.clone()), | ||
self.last_run, | ||
self.current, | ||
)?) | ||
.unwrap_or_else(|_| unreachable!("Cell is expected to be empty")); | ||
|
||
Ok(true) | ||
} | ||
|
||
/// Fetches the unique component from the `World`. | ||
/// | ||
/// Returns `true` if the component was fetched. | ||
/// | ||
/// ### Borrows | ||
/// | ||
/// - `Unique<T>` storage (shared) | ||
/// | ||
/// ### Errors | ||
/// | ||
/// - `Unique<T>` storage borrow failed (it can be initialized and borrowed elsewhere). | ||
pub fn fetch(&self) -> Result<bool, error::GetStorage> { | ||
if self.cell.get().is_some() { | ||
return Ok(false); | ||
} | ||
|
||
self.cell | ||
.set(UniqueView::borrow( | ||
self.all_storages, | ||
Some(self.all_borrow.clone()), | ||
self.last_run, | ||
self.current, | ||
)?) | ||
.unwrap_or_else(|_| unreachable!("Cell is expected to be empty")); | ||
|
||
Ok(true) | ||
} | ||
|
||
/// Gets the unique component from the `World`.\ | ||
/// Adds it to the `World` if not present. | ||
/// | ||
/// ### Borrows | ||
/// | ||
/// - `Unique<T>` storage (shared) | ||
/// | ||
/// ### Errors | ||
/// | ||
/// - `Unique<T>` storage borrow failed (it can be initialized and borrowed elsewhere). | ||
pub fn get_or_init( | ||
&self, | ||
f: impl FnOnce() -> T, | ||
) -> Result<&UniqueView<'v, T>, error::GetStorage> { | ||
if let Some(view) = self.cell.get() { | ||
return Ok(view); | ||
} | ||
|
||
let view = match UniqueView::borrow( | ||
self.all_storages, | ||
Some(self.all_borrow.clone()), | ||
self.last_run, | ||
self.current, | ||
) { | ||
Ok(view) => view, | ||
Err(error::GetStorage::MissingStorage { .. }) => { | ||
self.all_storages.add_unique(f()); | ||
|
||
UniqueView::borrow( | ||
self.all_storages, | ||
Some(self.all_borrow.clone()), | ||
self.last_run, | ||
self.current, | ||
)? | ||
} | ||
Err(err) => return Err(err), | ||
}; | ||
|
||
self.cell | ||
.set(view) | ||
.unwrap_or_else(|_| unreachable!("Cell is expected to be empty")); | ||
|
||
Ok(self | ||
.cell | ||
.get() | ||
.unwrap_or_else(|| unreachable!("Cell is expected to be initialized"))) | ||
} | ||
} | ||
|
||
impl<'v, T: Unique + Default + Send + Sync> WorldBorrow for UniqueOrInitView<'v, T> { | ||
type WorldView<'a> = UniqueOrInitView<'a, T>; | ||
|
||
fn world_borrow( | ||
world: &World, | ||
last_run: Option<TrackingTimestamp>, | ||
current: TrackingTimestamp, | ||
) -> Result<Self::WorldView<'_>, error::GetStorage> { | ||
let all_storages = world | ||
.all_storages() | ||
.map_err(error::GetStorage::AllStoragesBorrow)?; | ||
|
||
let (all_storages, all_borrow) = unsafe { ARef::destructure(all_storages) }; | ||
let cell = OnceCell::new(); | ||
|
||
match UniqueView::borrow(all_storages, Some(all_borrow.clone()), last_run, current) { | ||
Ok(view) => cell | ||
.set(view) | ||
.unwrap_or_else(|_| unreachable!("Cell is expected to be empty")), | ||
Err(error::GetStorage::MissingStorage { .. }) => {} | ||
Err(err) => return Err(err), | ||
}; | ||
|
||
Ok(UniqueOrInitView { | ||
cell, | ||
all_storages, | ||
all_borrow, | ||
last_run, | ||
current, | ||
}) | ||
} | ||
} | ||
|
||
unsafe impl<'v, T: Unique + Default + Send + Sync> BorrowInfo for UniqueOrInitView<'v, T> { | ||
fn borrow_info(info: &mut Vec<TypeInfo>) { | ||
UniqueView::<T>::borrow_info(info); | ||
} | ||
|
||
fn enable_tracking( | ||
enable_tracking_fn: &mut Vec<fn(&AllStorages) -> Result<(), error::GetStorage>>, | ||
) { | ||
UniqueView::<T>::enable_tracking(enable_tracking_fn); | ||
} | ||
} |
Oops, something went wrong.