1use once_map::OnceMap;
4use std::sync::Arc;
5
6use crate::prelude::*;
7
8mod iterator;
9mod typed;
10mod untyped;
11
12pub use iterator::*;
13pub use typed::*;
14pub use untyped::*;
15
16pub type AtomicComponentStore<T> = Arc<AtomicCell<ComponentStore<T>>>;
18pub type UntypedAtomicComponentStore = Arc<AtomicCell<UntypedComponentStore>>;
20
21#[derive(Default)]
26pub struct ComponentStores {
27 pub(crate) components: OnceMap<SchemaId, UntypedAtomicComponentStore>,
28}
29
30unsafe impl Sync for ComponentStores {}
33unsafe impl Send for ComponentStores {}
34
35impl Clone for ComponentStores {
36 fn clone(&self) -> Self {
37 Self {
38 components: self
39 .components
40 .read_only_view()
41 .iter()
42 .map(|(&k, v)| (k, Arc::new((**v).clone())))
45 .collect(),
46 }
47 }
48}
49
50impl ComponentStores {
51 pub fn get_cell<T: HasSchema>(&self) -> AtomicComponentStore<T> {
53 let untyped = self.get_cell_by_schema(T::schema());
54
55 unsafe {
58 std::mem::transmute::<
59 Arc<AtomicCell<UntypedComponentStore>>,
60 Arc<AtomicCell<ComponentStore<T>>>,
61 >(untyped)
62 }
63 }
64
65 pub fn get<T: HasSchema>(&self) -> &AtomicCell<ComponentStore<T>> {
69 let schema = T::schema();
70 let atomiccell = self.get_by_schema(schema);
71
72 unsafe {
74 std::mem::transmute::<&AtomicCell<UntypedComponentStore>, &AtomicCell<ComponentStore<T>>>(
75 atomiccell,
76 )
77 }
78 }
79
80 pub fn get_by_schema(&self, schema: &'static Schema) -> &AtomicCell<UntypedComponentStore> {
82 self.components.insert(schema.id(), |_| {
83 Arc::new(AtomicCell::new(UntypedComponentStore::new(schema)))
84 })
85 }
86
87 pub fn get_cell_by_schema(
89 &self,
90 schema: &'static Schema,
91 ) -> Arc<AtomicCell<UntypedComponentStore>> {
92 self.components.map_insert(
93 schema.id(),
94 |_| Arc::new(AtomicCell::new(UntypedComponentStore::new(schema))),
95 |_key, value| value.clone(),
96 )
97 }
98}
99
100#[cfg(test)]
101mod test {
102 use crate::prelude::*;
103
104 #[derive(Clone, Copy, HasSchema, Default)]
105 #[repr(C)]
106 struct MyData(pub i32);
107
108 #[test]
109 fn borrow_many_mut() {
110 World::new().run_system(
111 |mut entities: ResMut<Entities>, mut my_datas: CompMut<MyData>| {
112 let ent1 = entities.create();
113 let ent2 = entities.create();
114
115 my_datas.insert(ent1, MyData(7));
116 my_datas.insert(ent2, MyData(8));
117
118 {
119 let [data2, data1] = my_datas.get_many_mut([ent2, ent1]).unwrap_many();
120
121 data1.0 = 0;
122 data2.0 = 1;
123 }
124
125 assert_eq!(my_datas.get(ent1).unwrap().0, 0);
126 assert_eq!(my_datas.get(ent2).unwrap().0, 1);
127 },
128 (),
129 );
130 }
131
132 #[test]
133 #[should_panic = "must be unique"]
134 fn borrow_many_overlapping_mut() {
135 World::new().run_system(
136 |mut entities: ResMut<Entities>, mut my_datas: CompMut<MyData>| {
137 let ent1 = entities.create();
138 let ent2 = entities.create();
139
140 my_datas.insert(ent1, MyData(1));
141 my_datas.insert(ent2, MyData(2));
142
143 my_datas.get_many_mut([ent1, ent2, ent1]).unwrap_many();
144 },
145 (),
146 )
147 }
148}