mod borrow_info;
#[cfg(feature = "thread_local")]
mod non_send;
#[cfg(feature = "thread_local")]
mod non_send_sync;
#[cfg(feature = "thread_local")]
mod non_sync;
mod world_borrow;
pub use borrow_info::BorrowInfo;
#[cfg(feature = "thread_local")]
pub use non_send::NonSend;
#[cfg(feature = "thread_local")]
pub use non_send_sync::NonSendSync;
#[cfg(feature = "thread_local")]
pub use non_sync::NonSync;
pub use world_borrow::WorldBorrow;
use crate::all_storages::{AllStorages, CustomStorageAccess};
use crate::atomic_refcell::{ARef, ARefMut, SharedBorrow};
use crate::component::{Component, Unique};
use crate::error;
use crate::sparse_set::SparseSet;
use crate::system::Nothing;
use crate::tracking::{Tracking, TrackingTimestamp};
use crate::unique::UniqueStorage;
use crate::views::{EntitiesView, EntitiesViewMut, UniqueView, UniqueViewMut, View, ViewMut};
use core::marker::PhantomData;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
pub enum Mutability {
    #[allow(missing_docs)]
    Shared,
    #[allow(missing_docs)]
    Exclusive,
}
pub trait Borrow {
    #[allow(missing_docs)]
    type View<'a>;
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage>;
}
impl Borrow for Nothing {
    type View<'a> = ();
    fn borrow<'a>(
        _all_storages: &'a AllStorages,
        _all_borrow: Option<SharedBorrow<'a>>,
        _last_run: Option<TrackingTimestamp>,
        _current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        Ok(())
    }
}
impl Borrow for () {
    type View<'a> = ();
    #[inline]
    fn borrow<'a>(
        _all_storages: &'a AllStorages,
        _all_borrow: Option<SharedBorrow<'a>>,
        _last_run: Option<TrackingTimestamp>,
        _current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage>
    where
        Self: Sized,
    {
        Ok(())
    }
}
impl Borrow for EntitiesView<'_> {
    type View<'a> = EntitiesView<'a>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        _last_run: Option<TrackingTimestamp>,
        _current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let entities = all_storages.entities()?;
        let (entities, borrow) = unsafe { ARef::destructure(entities) };
        Ok(EntitiesView {
            entities,
            borrow: Some(borrow),
            all_borrow,
        })
    }
}
impl Borrow for EntitiesViewMut<'_> {
    type View<'a> = EntitiesViewMut<'a>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        _last_run: Option<TrackingTimestamp>,
        _current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let entities = all_storages.entities_mut()?;
        let (entities, borrow) = unsafe { ARefMut::destructure(entities) };
        Ok(EntitiesViewMut {
            entities,
            _borrow: Some(borrow),
            _all_borrow: all_borrow,
        })
    }
}
impl<T: Send + Sync + Component, Track> Borrow for View<'_, T, Track>
where
    Track: Tracking,
{
    type View<'a> = View<'a, T, Track>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view = all_storages.custom_storage_or_insert(SparseSet::new)?;
        let (sparse_set, borrow) = unsafe { ARef::destructure(view) };
        sparse_set.check_tracking::<Track>()?;
        Ok(View::new(sparse_set, borrow, all_borrow, last_run, current))
    }
}
#[cfg(feature = "thread_local")]
impl<T: Sync + Component, Track> Borrow for NonSend<View<'_, T, Track>>
where
    Track: Tracking,
{
    type View<'a> = NonSend<View<'a, T, Track>>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view = all_storages.custom_storage_or_insert_non_send(|| NonSend(SparseSet::new()))?;
        let (sparse_set, borrow) = unsafe { ARef::destructure(view) };
        sparse_set.check_tracking::<Track>()?;
        Ok(NonSend(View {
            last_insertion: last_run.unwrap_or(sparse_set.last_insert),
            last_modification: last_run.unwrap_or(sparse_set.last_modified),
            last_removal_or_deletion: last_run.unwrap_or(current),
            current,
            sparse_set,
            borrow,
            all_borrow,
            phantom: PhantomData,
        }))
    }
}
#[cfg(feature = "thread_local")]
impl<T: Send + Component, Track> Borrow for NonSync<View<'_, T, Track>>
where
    Track: Tracking,
{
    type View<'a> = NonSync<View<'a, T, Track>>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view = all_storages.custom_storage_or_insert_non_sync(|| NonSync(SparseSet::new()))?;
        let (sparse_set, borrow) = unsafe { ARef::destructure(view) };
        sparse_set.check_tracking::<Track>()?;
        Ok(NonSync(View {
            last_insertion: last_run.unwrap_or(sparse_set.last_insert),
            last_modification: last_run.unwrap_or(sparse_set.last_modified),
            last_removal_or_deletion: last_run.unwrap_or(current),
            current,
            sparse_set,
            borrow,
            all_borrow,
            phantom: PhantomData,
        }))
    }
}
#[cfg(feature = "thread_local")]
impl<T: Component, Track> Borrow for NonSendSync<View<'_, T, Track>>
where
    Track: Tracking,
{
    type View<'a> = NonSendSync<View<'a, T, Track>>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view = all_storages
            .custom_storage_or_insert_non_send_sync(|| NonSendSync(SparseSet::new()))?;
        let (sparse_set, borrow) = unsafe { ARef::destructure(view) };
        sparse_set.check_tracking::<Track>()?;
        Ok(NonSendSync(View {
            last_insertion: last_run.unwrap_or(sparse_set.last_insert),
            last_modification: last_run.unwrap_or(sparse_set.last_modified),
            last_removal_or_deletion: last_run.unwrap_or(current),
            current,
            sparse_set,
            borrow,
            all_borrow,
            phantom: PhantomData,
        }))
    }
}
impl<T: Send + Sync + Component, Track> Borrow for ViewMut<'_, T, Track>
where
    Track: Tracking,
{
    type View<'a> = ViewMut<'a, T, Track>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view = all_storages.custom_storage_or_insert_mut(SparseSet::new)?;
        let (sparse_set, borrow) = unsafe { ARefMut::destructure(view) };
        sparse_set.check_tracking::<Track>()?;
        Ok(ViewMut {
            last_insertion: last_run.unwrap_or(sparse_set.last_insert),
            last_modification: last_run.unwrap_or(sparse_set.last_modified),
            last_removal_or_deletion: last_run.unwrap_or(current),
            current,
            sparse_set,
            borrow,
            all_borrow,
            phantom: PhantomData,
        })
    }
}
#[cfg(feature = "thread_local")]
impl<T: Sync + Component, Track> Borrow for NonSend<ViewMut<'_, T, Track>>
where
    Track: Tracking,
{
    type View<'a> = NonSend<ViewMut<'a, T, Track>>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view =
            all_storages.custom_storage_or_insert_non_send_mut(|| NonSend(SparseSet::new()))?;
        let (sparse_set, borrow) = unsafe { ARefMut::destructure(view) };
        sparse_set.check_tracking::<Track>()?;
        Ok(NonSend(ViewMut {
            last_insertion: last_run.unwrap_or(sparse_set.last_insert),
            last_modification: last_run.unwrap_or(sparse_set.last_modified),
            last_removal_or_deletion: last_run.unwrap_or(current),
            current,
            sparse_set,
            borrow: borrow,
            all_borrow: all_borrow,
            phantom: PhantomData,
        }))
    }
}
#[cfg(feature = "thread_local")]
impl<T: Send + Component, Track> Borrow for NonSync<ViewMut<'_, T, Track>>
where
    Track: Tracking,
{
    type View<'a> = NonSync<ViewMut<'a, T, Track>>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view =
            all_storages.custom_storage_or_insert_non_sync_mut(|| NonSync(SparseSet::new()))?;
        let (sparse_set, borrow) = unsafe { ARefMut::destructure(view) };
        sparse_set.check_tracking::<Track>()?;
        Ok(NonSync(ViewMut {
            last_insertion: last_run.unwrap_or(sparse_set.last_insert),
            last_modification: last_run.unwrap_or(sparse_set.last_modified),
            last_removal_or_deletion: last_run.unwrap_or(current),
            current,
            sparse_set,
            borrow: borrow,
            all_borrow: all_borrow,
            phantom: PhantomData,
        }))
    }
}
#[cfg(feature = "thread_local")]
impl<T: Component, Track> Borrow for NonSendSync<ViewMut<'_, T, Track>>
where
    Track: Tracking,
{
    type View<'a> = NonSendSync<ViewMut<'a, T, Track>>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view = all_storages
            .custom_storage_or_insert_non_send_sync_mut(|| NonSendSync(SparseSet::new()))?;
        let (sparse_set, borrow) = unsafe { ARefMut::destructure(view) };
        sparse_set.check_tracking::<Track>()?;
        Ok(NonSendSync(ViewMut {
            last_insertion: last_run.unwrap_or(sparse_set.last_insert),
            last_modification: last_run.unwrap_or(sparse_set.last_modified),
            last_removal_or_deletion: last_run.unwrap_or(current),
            current,
            sparse_set,
            borrow: borrow,
            all_borrow: all_borrow,
            phantom: PhantomData,
        }))
    }
}
impl<T: Send + Sync + Unique> Borrow for UniqueView<'_, T> {
    type View<'a> = UniqueView<'a, T>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view = all_storages.custom_storage()?;
        let (unique, borrow) = unsafe { ARef::destructure(view) };
        Ok(UniqueView {
            unique,
            borrow: Some(borrow),
            all_borrow,
            last_insertion: last_run.unwrap_or(unique.last_insert),
            last_modification: last_run.unwrap_or(unique.last_modification),
            current,
        })
    }
}
#[cfg(feature = "thread_local")]
impl<T: Sync + Unique> Borrow for NonSend<UniqueView<'_, T>> {
    type View<'a> = NonSend<UniqueView<'a, T>>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view = all_storages.custom_storage()?;
        let (unique, borrow) = unsafe { ARef::destructure(view) };
        Ok(NonSend(UniqueView {
            unique,
            borrow: Some(borrow),
            all_borrow,
            last_insertion: last_run.unwrap_or(unique.last_insert),
            last_modification: last_run.unwrap_or(unique.last_modification),
            current,
        }))
    }
}
#[cfg(feature = "thread_local")]
impl<T: Send + Unique> Borrow for NonSync<UniqueView<'_, T>> {
    type View<'a> = NonSync<UniqueView<'a, T>>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view = all_storages.custom_storage()?;
        let (unique, borrow) = unsafe { ARef::destructure(view) };
        Ok(NonSync(UniqueView {
            unique,
            borrow: Some(borrow),
            all_borrow,
            last_insertion: last_run.unwrap_or(unique.last_insert),
            last_modification: last_run.unwrap_or(unique.last_modification),
            current,
        }))
    }
}
#[cfg(feature = "thread_local")]
impl<T: Unique> Borrow for NonSendSync<UniqueView<'_, T>> {
    type View<'a> = NonSendSync<UniqueView<'a, T>>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view = all_storages.custom_storage()?;
        let (unique, borrow) = unsafe { ARef::destructure(view) };
        Ok(NonSendSync(UniqueView {
            unique,
            borrow: Some(borrow),
            all_borrow,
            last_insertion: last_run.unwrap_or(unique.last_insert),
            last_modification: last_run.unwrap_or(unique.last_modification),
            current,
        }))
    }
}
impl<T: Send + Sync + Unique> Borrow for UniqueViewMut<'_, T> {
    type View<'a> = UniqueViewMut<'a, T>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view = all_storages.custom_storage_mut::<UniqueStorage<T>>()?;
        let (unique, borrow) = unsafe { ARefMut::destructure(view) };
        Ok(UniqueViewMut {
            last_insertion: last_run.unwrap_or(unique.last_insert),
            last_modification: last_run.unwrap_or(unique.last_modification),
            current,
            unique,
            _borrow: Some(borrow),
            _all_borrow: all_borrow,
        })
    }
}
#[cfg(feature = "thread_local")]
impl<T: Sync + Unique> Borrow for NonSend<UniqueViewMut<'_, T>> {
    type View<'a> = NonSend<UniqueViewMut<'a, T>>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view = all_storages.custom_storage_mut::<UniqueStorage<T>>()?;
        let (unique, borrow) = unsafe { ARefMut::destructure(view) };
        Ok(NonSend(UniqueViewMut {
            last_insertion: last_run.unwrap_or(unique.last_insert),
            last_modification: last_run.unwrap_or(unique.last_modification),
            current,
            unique,
            _borrow: Some(borrow),
            _all_borrow: all_borrow,
        }))
    }
}
#[cfg(feature = "thread_local")]
impl<T: Send + Unique> Borrow for NonSync<UniqueViewMut<'_, T>> {
    type View<'a> = NonSync<UniqueViewMut<'a, T>>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view = all_storages.custom_storage_mut::<UniqueStorage<T>>()?;
        let (unique, borrow) = unsafe { ARefMut::destructure(view) };
        Ok(NonSync(UniqueViewMut {
            last_insertion: last_run.unwrap_or(unique.last_insert),
            last_modification: last_run.unwrap_or(unique.last_modification),
            current,
            unique,
            _borrow: Some(borrow),
            _all_borrow: all_borrow,
        }))
    }
}
#[cfg(feature = "thread_local")]
impl<T: Unique> Borrow for NonSendSync<UniqueViewMut<'_, T>> {
    type View<'a> = NonSendSync<UniqueViewMut<'a, T>>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        let view = all_storages.custom_storage_mut::<UniqueStorage<T>>()?;
        let (unique, borrow) = unsafe { ARefMut::destructure(view) };
        Ok(NonSendSync(UniqueViewMut {
            last_insertion: last_run.unwrap_or(unique.last_insert),
            last_modification: last_run.unwrap_or(unique.last_modification),
            current,
            unique,
            _borrow: Some(borrow),
            _all_borrow: all_borrow,
        }))
    }
}
impl<T: Borrow> Borrow for Option<T> {
    type View<'a> = Option<T::View<'a>>;
    #[inline]
    fn borrow<'a>(
        all_storages: &'a AllStorages,
        all_borrow: Option<SharedBorrow<'a>>,
        last_run: Option<TrackingTimestamp>,
        current: TrackingTimestamp,
    ) -> Result<Self::View<'a>, error::GetStorage> {
        Ok(T::borrow(all_storages, all_borrow, last_run, current).ok())
    }
}
macro_rules! impl_borrow {
    ($(($type: ident, $index: tt))+) => {
        impl<$($type: Borrow),+> Borrow for ($($type,)+) {
            type View<'a> = ($($type::View<'a>,)+);
            #[inline]
            fn borrow<'a>(
                all_storages: &'a AllStorages,
                all_borrow: Option<SharedBorrow<'a>>,
                last_run: Option<TrackingTimestamp>,
                current: TrackingTimestamp
            ) -> Result<Self::View<'a>, error::GetStorage> {
                Ok(($($type::borrow(all_storages, all_borrow.clone(), last_run, current)?,)+))
            }
        }
    }
}
macro_rules! borrow {
    ($(($type: ident, $index: tt))*;($type1: ident, $index1: tt) $(($queue_type: ident, $queue_index: tt))*) => {
        impl_borrow![$(($type, $index))*];
        borrow![$(($type, $index))* ($type1, $index1); $(($queue_type, $queue_index))*];
    };
    ($(($type: ident, $index: tt))*;) => {
        impl_borrow![$(($type, $index))*];
    }
}
borrow![(A, 0); (B, 1) (C, 2) (D, 3) (E, 4) (F, 5) (G, 6) (H, 7) (I, 8) (J, 9)];