shipyard 0.11.2

Entity Component System
Documentation
use core::any::type_name;
use shipyard::advanced::StorageId;
use shipyard::error;
use shipyard::sparse_set::SparseSet;
use shipyard::*;

#[allow(unused)]
struct USIZE(usize);
impl Component for USIZE {
    type Tracking = track::Untracked;
}
impl Unique for USIZE {}

#[derive(PartialEq, Eq, Debug)]
struct U32(u32);
impl Component for U32 {
    type Tracking = track::Untracked;
}
impl Unique for U32 {}

#[derive(PartialEq, Eq, Debug)]
struct I32(i32);
impl Component for I32 {
    type Tracking = track::Untracked;
}

#[allow(unused)]
#[cfg(feature = "thread_local")]
struct NotSend(*const ());

#[cfg(feature = "thread_local")]
unsafe impl Sync for NotSend {}

#[cfg(feature = "thread_local")]
impl Component for NotSend {
    type Tracking = track::Untracked;
}
#[cfg(feature = "thread_local")]
impl Unique for NotSend {}

#[allow(unused)]
#[cfg(feature = "thread_local")]
struct NotSync(*const ());

#[cfg(feature = "thread_local")]
unsafe impl Send for NotSync {}

#[cfg(feature = "thread_local")]
impl Component for NotSync {
    type Tracking = track::Untracked;
}
#[cfg(feature = "thread_local")]
impl Unique for NotSync {}

#[allow(unused)]
#[cfg(feature = "thread_local")]
struct NotSendSync(*const ());

#[cfg(feature = "thread_local")]
impl Component for NotSendSync {
    type Tracking = track::Untracked;
}
#[cfg(feature = "thread_local")]
impl Unique for NotSendSync {}

#[test]
fn simple_borrow() {
    let world = World::new();

    let u32s = world.borrow::<View<U32>>().unwrap();
    assert_eq!(u32s.len(), 0);
}

#[test]
fn option_borrow() {
    let world = World::new();

    let u32s = world.borrow::<Option<View<U32>>>().unwrap();

    let u32s = u32s.unwrap();
    assert_eq!(u32s.len(), 0);
    drop(u32s);
    let _i32s = world.borrow::<ViewMut<I32>>().unwrap();
    let other_i32s = world.borrow::<Option<View<I32>>>().unwrap();
    assert!(other_i32s.is_none());
}

#[test]
fn all_storages_simple_borrow() {
    let world = World::new();

    let all_storages = world.borrow::<AllStoragesViewMut>().unwrap();
    let u32s = all_storages.borrow::<View<U32>>().unwrap();
    assert_eq!(u32s.len(), 0);
}

#[test]
fn invalid_borrow() {
    let world = World::new();

    let _u32s = world.borrow::<ViewMut<U32>>().unwrap();
    assert_eq!(
        world.borrow::<ViewMut<U32>>().err(),
        Some(error::GetStorage::StorageBorrow {
            name: Some(type_name::<SparseSet<U32>>()),
            id: StorageId::of::<SparseSet<U32>>(),
            borrow: error::Borrow::Unique
        })
    );
}

#[test]
fn all_storages_invalid_borrow() {
    let world = World::new();

    let all_storages = world.borrow::<AllStoragesViewMut>().unwrap();
    let _u32s = all_storages.borrow::<ViewMut<U32>>().unwrap();
    assert_eq!(
        all_storages.borrow::<ViewMut<U32>>().err(),
        Some(error::GetStorage::StorageBorrow {
            name: Some(type_name::<SparseSet<U32>>()),
            id: StorageId::of::<SparseSet<U32>>(),
            borrow: error::Borrow::Unique
        })
    );
}

#[test]
fn double_borrow() {
    let world = World::new();

    let u32s = world.borrow::<ViewMut<U32>>().unwrap();
    drop(u32s);
    world.borrow::<ViewMut<U32>>().unwrap();
}

#[test]
fn all_storages_double_borrow() {
    let world = World::new();

    let all_storages = world.borrow::<AllStoragesViewMut>().unwrap();
    let u32s = all_storages.borrow::<ViewMut<U32>>().unwrap();
    drop(u32s);
    all_storages.borrow::<ViewMut<U32>>().unwrap();
}

#[test]
fn all_storages_option_borrow() {
    let world = World::new();
    let all_storages = world.borrow::<AllStoragesViewMut>().unwrap();

    let u32s = all_storages.borrow::<Option<View<U32>>>().unwrap();

    let u32s = u32s.unwrap();
    assert_eq!(u32s.len(), 0);
    drop(u32s);
    let _i32s = all_storages.borrow::<ViewMut<I32>>().unwrap();
    let other_i32s = all_storages.borrow::<Option<View<I32>>>().unwrap();
    assert!(other_i32s.is_none());
}

#[test]
#[cfg(feature = "thread_local")]
fn non_send_storage_in_other_thread() {
    let world = World::new();
    rayon::join(
        || {
            assert_eq!(
                world.borrow::<borrow::NonSend<ViewMut<NotSend>>>().err(),
                Some(error::GetStorage::StorageBorrow {
                    name: Some(type_name::<borrow::NonSend<SparseSet<NotSend>>>()),
                    id: StorageId::of::<borrow::NonSend<SparseSet<NotSend>>>(),
                    borrow: error::Borrow::WrongThread
                })
            )
        },
        || {},
    );
}

#[test]
#[cfg(feature = "thread_local")]
fn non_send_sync_storage_in_other_thread() {
    let world = World::new();
    rayon::join(
        || {
            assert_eq!(
                world
                    .borrow::<borrow::NonSendSync<View<NotSendSync>>>()
                    .err(),
                Some(error::GetStorage::StorageBorrow {
                    name: Some(type_name::<borrow::NonSendSync<SparseSet<NotSendSync>>>()),
                    id: StorageId::of::<borrow::NonSendSync<SparseSet<NotSendSync>>>(),
                    borrow: error::Borrow::WrongThread
                })
            )
        },
        || {},
    );
}

#[test]
fn add_unique_while_borrowing() {
    let world = World::new();
    world.add_unique(U32(0));
    let _s = world.borrow::<UniqueView<'_, U32>>().unwrap();
    world.add_unique(USIZE(0));
}

#[test]
fn sparse_set_and_unique() {
    let world = World::new();
    world.add_unique(U32(0));
    world
        .borrow::<(UniqueViewMut<U32>, ViewMut<U32>)>()
        .unwrap();
}

#[test]
#[cfg(feature = "thread_local")]
fn exhaustive_list() {
    let world = World::new();

    let _ = world.borrow::<(
        borrow::NonSend<View<NotSend>>,
        borrow::NonSync<View<NotSync>>,
        borrow::NonSendSync<View<NotSendSync>>,
        borrow::NonSend<ViewMut<NotSend>>,
        borrow::NonSync<ViewMut<NotSync>>,
        borrow::NonSendSync<ViewMut<NotSendSync>>,
    )>();

    world.run(|all_storages: AllStoragesViewMut| {
        let _ = all_storages.borrow::<(
            borrow::NonSend<View<NotSend>>,
            borrow::NonSync<View<NotSync>>,
            borrow::NonSendSync<View<NotSendSync>>,
            borrow::NonSend<ViewMut<NotSend>>,
            borrow::NonSync<ViewMut<NotSync>>,
            borrow::NonSendSync<ViewMut<NotSendSync>>,
        )>();
    });
}

#[test]
#[cfg(feature = "thread_local")]
fn unique_exhaustive_list() {
    let world = World::new();

    world.add_unique_non_send(NotSend(&()));
    world.add_unique_non_sync(NotSync(&()));
    world.add_unique_non_send_sync(NotSendSync(&()));

    let _ = world.borrow::<(
        borrow::NonSend<UniqueView<NotSend>>,
        borrow::NonSync<UniqueView<NotSync>>,
        borrow::NonSendSync<UniqueView<NotSendSync>>,
        borrow::NonSend<UniqueViewMut<NotSend>>,
        borrow::NonSync<UniqueViewMut<NotSync>>,
        borrow::NonSendSync<UniqueViewMut<NotSendSync>>,
    )>();

    world.run(|all_storages: AllStoragesViewMut| {
        let _ = all_storages.borrow::<(
            borrow::NonSend<UniqueView<NotSend>>,
            borrow::NonSync<UniqueView<NotSync>>,
            borrow::NonSendSync<UniqueView<NotSendSync>>,
            borrow::NonSend<UniqueViewMut<NotSend>>,
            borrow::NonSync<UniqueViewMut<NotSync>>,
            borrow::NonSendSync<UniqueViewMut<NotSendSync>>,
        )>();
    });
}