use core::{
any::{type_name, TypeId},
marker::PhantomData,
ops::{Deref, DerefMut},
ptr::NonNull,
};
use atomicell::{Ref, RefMut};
use crate::{
archetype::Archetype,
component::ComponentInfo,
system::{Access, ActionBufferQueue},
type_id,
world::World,
};
use super::{FnArg, FnArgState};
#[repr(transparent)]
pub struct Res<'a, T: ?Sized> {
inner: Ref<'a, T>,
}
impl<'a, T> Deref for Res<'a, T>
where
T: ?Sized,
{
type Target = T;
#[inline(always)]
fn deref(&self) -> &T {
self.inner.deref()
}
}
impl<'a, T> Res<'a, T>
where
T: ?Sized,
{
#[inline(always)]
pub fn inner(self) -> Ref<'a, T> {
self.inner
}
}
pub struct ResState<T> {
marker: PhantomData<fn() -> T>,
}
impl<T> Default for ResState<T> {
#[inline(always)]
fn default() -> Self {
Self {
marker: PhantomData,
}
}
}
impl<'a, T> FnArg for Res<'a, T>
where
T: Sync + 'static,
{
type State = ResState<T>;
}
unsafe impl<T> FnArgState for ResState<T>
where
T: Sync + 'static,
{
type Arg<'a> = Res<'a, T>;
#[inline(always)]
fn new() -> Self {
Self::default()
}
#[inline(always)]
fn is_local(&self) -> bool {
false
}
#[inline(always)]
fn world_access(&self) -> Option<Access> {
Some(Access::Read)
}
#[inline(always)]
fn visit_archetype(&self, _archetype: &Archetype) -> bool {
false
}
#[inline(always)]
fn borrows_components_at_runtime(&self) -> bool {
false
}
#[inline(always)]
fn component_access(&self, _comp: &ComponentInfo) -> Option<Access> {
None
}
#[inline(always)]
fn resource_type_access(&self, ty: TypeId) -> Option<Access> {
if ty == type_id::<T>() {
Some(Access::Read)
} else {
None
}
}
#[inline(always)]
unsafe fn get_unchecked<'a>(
&'a mut self,
world: NonNull<World>,
_queue: &mut dyn ActionBufferQueue,
) -> Res<'a, T> {
let world = unsafe { world.as_ref() };
match world.get_resource() {
Some(r) => Res { inner: r },
None => missing_resource::<T>(),
}
}
}
pub struct ResMut<'a, T: ?Sized> {
inner: RefMut<'a, T>,
}
impl<'a, T> Deref for ResMut<'a, T>
where
T: ?Sized,
{
type Target = T;
#[inline(always)]
fn deref(&self) -> &T {
self.inner.deref()
}
}
impl<'a, T> DerefMut for ResMut<'a, T>
where
T: ?Sized,
{
#[inline(always)]
fn deref_mut(&mut self) -> &mut T {
self.inner.deref_mut()
}
}
impl<'a, T> ResMut<'a, T>
where
T: ?Sized,
{
#[inline(always)]
pub fn inner(self) -> RefMut<'a, T> {
self.inner
}
}
pub struct ResMutState<T> {
marker: PhantomData<fn() -> T>,
}
impl<T> Default for ResMutState<T> {
#[inline(always)]
fn default() -> Self {
Self {
marker: PhantomData,
}
}
}
impl<'a, T> FnArg for ResMut<'a, T>
where
T: Send + 'static,
{
type State = ResMutState<T>;
}
unsafe impl<T> FnArgState for ResMutState<T>
where
T: Send + 'static,
{
type Arg<'a> = ResMut<'a, T>;
#[inline(always)]
fn new() -> Self {
Self::default()
}
#[inline(always)]
fn is_local(&self) -> bool {
false
}
#[inline(always)]
fn world_access(&self) -> Option<Access> {
Some(Access::Read)
}
#[inline(always)]
fn visit_archetype(&self, _archetype: &Archetype) -> bool {
false
}
#[inline(always)]
fn borrows_components_at_runtime(&self) -> bool {
false
}
#[inline(always)]
fn component_access(&self, _comp: &ComponentInfo) -> Option<Access> {
None
}
#[inline(always)]
fn resource_type_access(&self, ty: TypeId) -> Option<Access> {
if ty == type_id::<T>() {
Some(Access::Write)
} else {
None
}
}
#[inline(always)]
unsafe fn get_unchecked<'a>(
&'a mut self,
world: NonNull<World>,
_queue: &mut dyn ActionBufferQueue,
) -> ResMut<'a, T> {
let world = unsafe { world.as_ref() };
match world.get_resource_mut() {
Some(r) => ResMut { inner: r },
None => missing_resource::<T>(),
}
}
}
pub struct ResNoSync<'a, T: ?Sized> {
inner: Ref<'a, T>,
}
impl<'a, T> Deref for ResNoSync<'a, T>
where
T: ?Sized,
{
type Target = T;
#[inline(always)]
fn deref(&self) -> &T {
self.inner.deref()
}
}
impl<'a, T> ResNoSync<'a, T>
where
T: ?Sized,
{
#[inline(always)]
pub fn inner(self) -> Ref<'a, T> {
self.inner
}
}
pub struct ResNoSyncState<T> {
marker: PhantomData<fn() -> T>,
}
impl<T> Default for ResNoSyncState<T> {
#[inline(always)]
fn default() -> Self {
Self {
marker: PhantomData,
}
}
}
impl<'a, T> FnArg for ResNoSync<'a, T>
where
T: 'static,
{
type State = ResNoSyncState<T>;
}
unsafe impl<T> FnArgState for ResNoSyncState<T>
where
T: 'static,
{
type Arg<'a> = ResNoSync<'a, T>;
#[inline(always)]
fn new() -> Self {
Self::default()
}
#[inline(always)]
fn is_local(&self) -> bool {
true
}
#[inline(always)]
fn world_access(&self) -> Option<Access> {
Some(Access::Read)
}
#[inline(always)]
fn visit_archetype(&self, _archetype: &Archetype) -> bool {
false
}
#[inline(always)]
fn borrows_components_at_runtime(&self) -> bool {
false
}
#[inline(always)]
fn component_access(&self, _comp: &ComponentInfo) -> Option<Access> {
None
}
#[inline(always)]
fn resource_type_access(&self, ty: TypeId) -> Option<Access> {
if ty == type_id::<T>() {
Some(Access::Read)
} else {
None
}
}
#[inline(always)]
unsafe fn get_unchecked<'a>(
&'a mut self,
world: NonNull<World>,
_queue: &mut dyn ActionBufferQueue,
) -> ResNoSync<'a, T> {
let world = unsafe { world.as_ref() };
match unsafe { world.get_local_resource() } {
Some(r) => ResNoSync { inner: r },
None => missing_resource::<T>(),
}
}
}
pub struct ResMutNoSend<'a, T: ?Sized> {
inner: RefMut<'a, T>,
}
impl<'a, T> Deref for ResMutNoSend<'a, T>
where
T: ?Sized,
{
type Target = T;
#[inline(always)]
fn deref(&self) -> &T {
self.inner.deref()
}
}
impl<'a, T> DerefMut for ResMutNoSend<'a, T>
where
T: ?Sized,
{
#[inline(always)]
fn deref_mut(&mut self) -> &mut T {
self.inner.deref_mut()
}
}
impl<'a, T> ResMutNoSend<'a, T>
where
T: ?Sized,
{
#[inline(always)]
pub fn inner(self) -> RefMut<'a, T> {
self.inner
}
}
pub struct ResMutNoSendState<T> {
marker: PhantomData<fn() -> T>,
}
impl<T> Default for ResMutNoSendState<T> {
#[inline(always)]
fn default() -> Self {
Self {
marker: PhantomData,
}
}
}
impl<'a, T> FnArg for ResMutNoSend<'a, T>
where
T: 'static,
{
type State = ResMutNoSendState<T>;
}
unsafe impl<T> FnArgState for ResMutNoSendState<T>
where
T: 'static,
{
type Arg<'a> = ResMutNoSend<'a, T>;
#[inline(always)]
fn new() -> Self {
Self::default()
}
#[inline(always)]
fn is_local(&self) -> bool {
true
}
#[inline(always)]
fn world_access(&self) -> Option<Access> {
Some(Access::Read)
}
#[inline(always)]
fn visit_archetype(&self, _archetype: &Archetype) -> bool {
false
}
#[inline(always)]
fn borrows_components_at_runtime(&self) -> bool {
false
}
#[inline(always)]
fn component_access(&self, _comp: &ComponentInfo) -> Option<Access> {
None
}
#[inline(always)]
fn resource_type_access(&self, ty: TypeId) -> Option<Access> {
if ty == type_id::<T>() {
Some(Access::Write)
} else {
None
}
}
#[inline(always)]
unsafe fn get_unchecked<'a>(
&'a mut self,
world: NonNull<World>,
_queue: &mut dyn ActionBufferQueue,
) -> ResMutNoSend<'a, T> {
let world = unsafe { world.as_ref() };
match unsafe { world.get_local_resource_mut() } {
Some(r) => ResMutNoSend { inner: r },
None => missing_resource::<T>(),
}
}
}
fn missing_resource<T>() -> ! {
panic!("Missing resource '{}'", type_name::<T>())
}