use core::ops::Index;
use crate::{
entity::{AliveEntity, Entity, Location},
query::{ImmutableQuery, Query, QueryItem, Read},
view::get_at,
EntityError, NoSuchEntity,
};
use super::{expect_alive, expect_match, BorrowState, ViewValue};
impl<Q, F, B> ViewValue<'_, Q, F, B>
where
Q: Query,
F: Query,
B: BorrowState,
{
#[inline(always)]
pub fn get_mut(&mut self, entity: impl AliveEntity) -> Option<QueryItem<Q>> {
let loc = entity.locate(self.entity_set);
if loc.arch == u32::MAX {
return Query::reserved_entity_item(&self.query, entity.id(), loc.idx);
}
self.acquire_borrow();
unsafe { self._get(loc) }
}
#[inline(always)]
pub fn try_get_mut(&mut self, entity: impl Entity) -> Result<QueryItem<Q>, EntityError> {
let loc = entity.lookup(self.entity_set).ok_or(NoSuchEntity)?;
if loc.arch == u32::MAX {
return Query::reserved_entity_item(&self.query, entity.id(), loc.idx)
.ok_or(EntityError::Mismatch);
}
self.acquire_borrow();
unsafe { self._get(loc) }.ok_or(EntityError::Mismatch)
}
#[inline(always)]
#[track_caller]
pub fn expect_mut(&mut self, entity: impl Entity) -> QueryItem<Q> {
let loc = expect_alive(entity.lookup(self.entity_set));
if loc.arch == u32::MAX {
return expect_match(Query::reserved_entity_item(
&self.query,
entity.id(),
loc.idx,
));
}
self.acquire_borrow();
expect_match(unsafe { self._get(loc) })
}
#[inline(always)]
pub fn map_mut<Fun, R>(&mut self, entity: impl AliveEntity, f: Fun) -> Option<R>
where
Fun: FnOnce(QueryItem<Q>) -> R,
{
let loc = entity.locate(self.entity_set);
if loc.arch == u32::MAX {
return Query::reserved_entity_item(&self.query, entity.id(), loc.idx).map(f);
}
self.with_borrow(loc.arch, || unsafe { self._get(loc) }.map(f))
}
#[inline(always)]
pub fn try_map_mut<Fun, R>(&mut self, entity: impl Entity, f: Fun) -> Result<R, EntityError>
where
Fun: FnOnce(QueryItem<Q>) -> R,
{
let loc = entity
.lookup(self.entity_set)
.ok_or(EntityError::NoSuchEntity)?;
if loc.arch == u32::MAX {
return Query::reserved_entity_item(&self.query, entity.id(), loc.idx)
.map(f)
.ok_or(EntityError::Mismatch);
}
self.with_borrow(loc.arch, || unsafe { self._get(loc) }.map(f))
.ok_or(EntityError::Mismatch)
}
#[inline(always)]
unsafe fn _get(&self, loc: Location) -> Option<QueryItem<Q>> {
debug_assert_ne!(loc.arch, u32::MAX);
get_at(
self.query,
self.filter,
self.epochs,
&self.archetypes[loc.arch as usize],
loc,
)
}
}
impl<Q, F, B> ViewValue<'_, Q, F, B>
where
Q: ImmutableQuery,
F: ImmutableQuery,
B: BorrowState,
{
#[inline(always)]
pub fn get(&self, entity: impl AliveEntity) -> Option<QueryItem<Q>> {
let loc = entity.locate(self.entity_set);
if loc.arch == u32::MAX {
return Query::reserved_entity_item(&self.query, entity.id(), loc.idx);
}
self.acquire_borrow();
unsafe { self._get(loc) }
}
#[inline(always)]
pub fn try_get(&self, entity: impl Entity) -> Result<QueryItem<Q>, EntityError> {
let loc = entity.lookup(self.entity_set).ok_or(NoSuchEntity)?;
if loc.arch == u32::MAX {
return Query::reserved_entity_item(&self.query, entity.id(), loc.idx)
.ok_or(EntityError::Mismatch);
}
self.acquire_borrow();
unsafe { self._get(loc) }.ok_or(EntityError::Mismatch)
}
#[inline(always)]
#[track_caller]
pub fn expect(&self, entity: impl Entity) -> QueryItem<Q> {
let loc = expect_alive(entity.lookup(self.entity_set));
if loc.arch == u32::MAX {
return expect_match(Query::reserved_entity_item(
&self.query,
entity.id(),
loc.idx,
));
}
self.acquire_borrow();
expect_match(unsafe { self._get(loc) })
}
#[inline(always)]
pub fn map<Fun, R>(&self, entity: impl AliveEntity, f: Fun) -> Option<R>
where
Fun: FnOnce(QueryItem<Q>) -> R,
{
let loc = entity.locate(self.entity_set);
if loc.arch == u32::MAX {
return Query::reserved_entity_item(&self.query, entity.id(), loc.idx).map(f);
}
self.with_borrow(loc.arch, || unsafe { self._get(loc) }.map(f))
}
#[inline(always)]
pub fn try_map<Fun, R>(&self, entity: impl Entity, f: Fun) -> Result<R, EntityError>
where
Fun: FnOnce(QueryItem<Q>) -> R,
{
let loc = entity
.lookup(self.entity_set)
.ok_or(EntityError::NoSuchEntity)?;
if loc.arch == u32::MAX {
return Query::reserved_entity_item(&self.query, entity.id(), loc.idx)
.map(f)
.ok_or(EntityError::Mismatch);
}
self.with_borrow(loc.arch, || unsafe { self._get(loc) }.map(f))
.ok_or(EntityError::Mismatch)
}
}
impl<E, T, F, B> Index<E> for ViewValue<'_, Read<T>, F, B>
where
E: Entity,
T: 'static + Sync,
F: ImmutableQuery,
B: BorrowState,
{
type Output = T;
#[inline(always)]
fn index(&self, entity: E) -> &T {
let entity = entity
.entity_loc(self.entity_set)
.expect("Entity is not alive");
self.get(entity)
.expect("Entity does not match view's query and filter")
}
}