1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#![doc = include_str!("../README.md")]
#![cfg_attr(doc, allow(unknown_lints))]
#![deny(rustdoc::all)]
#![warn(missing_docs)]

pub mod atomic {
    //! Atomic Refcell implmentation.
    //!
    //! Atomic Refcells are from the [`atomic_refcell`] crate.
    //!
    //! [`atomic_refcell`]: https://docs.rs/atomic_refcell
    pub use atomicell::*;
}
pub mod bitset;
pub mod components;
pub mod entities;
pub mod resources;
pub mod stage;
pub mod system;

pub use bones_schema as schema;
pub use bones_utils as utils;

mod world;
pub use world::{FromWorld, World};

/// The prelude.
pub mod prelude {
    pub use {
        atomicell::*, bitset_core::BitSet, bones_schema::prelude::*, bones_utils::prelude::*,
    };

    pub use crate::{
        bitset::*,
        components::*,
        entities::*,
        resources::*,
        stage::{CoreStage::*, *},
        system::*,
        FromWorld, UnwrapMany, World,
    };

    #[cfg(feature = "derive")]
    pub use bones_ecs_macros::*;

    // Make bones_schema available for derive macros
    pub use bones_schema;
}

/// Helper trait for unwraping each item in an array.
///
/// # Example
///
/// ```
/// # use bones_ecs::UnwrapMany;
/// let data = [Some(1), Some(2)];
/// let [data1, data2] = data.unwrap_many();
/// ```
pub trait UnwrapMany<const N: usize, T> {
    /// Unwrap all the items in an array.
    fn unwrap_many(self) -> [T; N];
}

impl<const N: usize, T> UnwrapMany<N, T> for [Option<T>; N] {
    fn unwrap_many(self) -> [T; N] {
        let mut iter = self.into_iter();
        std::array::from_fn(|_| iter.next().unwrap().unwrap())
    }
}
impl<const N: usize, T, E: std::fmt::Debug> UnwrapMany<N, T> for [Result<T, E>; N] {
    fn unwrap_many(self) -> [T; N] {
        let mut iter = self.into_iter();
        std::array::from_fn(|_| iter.next().unwrap().unwrap())
    }
}

#[cfg(test)]
mod test {
    use crate::prelude::*;

    #[test]
    fn insert_comp_with_gap() {
        let w = World::new();

        #[derive(HasSchema, Default, Clone)]
        #[repr(C)]
        struct MyComp(u32, u32, u32);

        w.run_system(
            |mut entities: ResMut<Entities>, mut comps: CompMut<MyComp>| {
                for _ in 0..3 {
                    entities.create();
                }

                let e = entities.create();
                comps.insert(e, default());
            },
            (),
        )
    }
}