1#[macro_use]
12extern crate derivative;
13extern crate hibitset;
14extern crate shred;
15extern crate specs;
16extern crate shrev;
17
18use std::hash::Hash;
19use std::marker::PhantomData;
20
21use hibitset::BitSet;
22use specs::storage::{UnprotectedStorage, ComponentEvent};
23use specs::{Component, Join, World, Tracked};
24use shrev::EventChannel;
25type Index = u32;
26
27pub trait Id: Copy + Eq + Hash + Ord + Send + Sync + Sized + 'static {
49 fn from_u32(value: u32) -> Self;
51
52 fn id(&self) -> u32;
54}
55
56#[derive(Derivative)]
64#[derivative(Default(bound = "D: Default"))]
65pub struct Storage<C, D: UnprotectedStorage<C>, I> {
66 data: D,
67 bitset: BitSet,
68 phantom: PhantomData<(C, I)>,
69}
70
71impl<C, D, I> Storage<C, D, I>
72where
73 C: Component,
74 D: UnprotectedStorage<C>,
75 I: Id,
76{
77 pub fn get(&self, id: I) -> Option<&C> {
81 match self.bitset.contains(id.id()) {
82 true => unsafe { Some(self.data.get(id.id())) },
83 false => None,
84 }
85 }
86
87 pub fn get_mut(&mut self, id: I) -> Option<&mut C> {
91 match self.bitset.contains(id.id()) {
92 true => unsafe { Some(self.data.get_mut(id.id())) },
93 false => None,
94 }
95 }
96
97 pub fn insert(&mut self, id: I, comp: C) -> Option<C> {
101 let old = match self.bitset.add(id.id()) {
102 true => unsafe { Some(self.data.remove(id.id())) },
103 false => None,
104 };
105
106 unsafe {
107 self.data.insert(id.id(), comp);
108 }
109
110 old
111 }
112
113 pub fn remove(&mut self, id: I) -> Option<C> {
115 match self.bitset.remove(id.id()) {
116 true => unsafe { Some(self.data.remove(id.id())) },
117 false => None,
118 }
119 }
120}
121
122impl<C, D, I> Tracked for Storage<C, D, I>
123 where D: Tracked + UnprotectedStorage<C>,
124 C: Component
125{
126 fn channel(&self) -> &EventChannel<ComponentEvent> { self.data.channel() }
127
128 fn channel_mut(&mut self) -> &mut EventChannel<ComponentEvent> { self.data.channel_mut() }
129}
130
131impl<C, D, I> Drop for Storage<C, D, I>
132where
133 D: UnprotectedStorage<C>,
134{
135 fn drop(&mut self) {
136 unsafe {
137 self.data.clean(&self.bitset);
138 }
139 }
140}
141
142impl<'a, C, D, I> Join for &'a Storage<C, D, I>
143where
144 D: UnprotectedStorage<C>,
145{
146 type Type = &'a C;
147 type Value = &'a D;
148 type Mask = &'a BitSet;
149
150 unsafe fn open(self) -> (Self::Mask, Self::Value) {
151 (&self.bitset, &self.data)
152 }
153
154 unsafe fn get(value: &mut Self::Value, id: Index) -> Self::Type {
155 (*value).get(id)
156 }
157}
158
159impl<'a, C, D, I> Join for &'a mut Storage<C, D, I>
160where
161 D: UnprotectedStorage<C>,
162{
163 type Type = &'a mut C;
164 type Value = &'a mut D;
165 type Mask = &'a BitSet;
166
167 unsafe fn open(self) -> (Self::Mask, Self::Value) {
168 (&self.bitset, &mut self.data)
169 }
170
171 unsafe fn get(value: &mut Self::Value, id: Index) -> Self::Type {
172 let value: *mut Self::Value = value as *mut Self::Value;
176 (*value).get_mut(id)
177 }
178}
179
180pub trait WorldExt {
182 fn register_tile_comp<C, I>(&mut self)
186 where
187 C: Component + Send + Sync,
188 C::Storage: Default,
189 I: Id;
190}
191
192impl WorldExt for World {
193 fn register_tile_comp<C, I>(&mut self)
194 where
195 C: Component + Send + Sync,
196 C::Storage: Default,
197 I: Id,
198 {
199 self.add_resource(Storage::<C, C::Storage, I>::default());
200 }
201}