diff options
Diffstat (limited to 'src/data')
| -rw-r--r-- | src/data/arena.rs | 87 | ||||
| -rw-r--r-- | src/data/coarena.rs | 30 | ||||
| -rw-r--r-- | src/data/component_set.rs | 106 | ||||
| -rw-r--r-- | src/data/mod.rs | 3 |
4 files changed, 177 insertions, 49 deletions
diff --git a/src/data/arena.rs b/src/data/arena.rs index 9d057b8..bc7176d 100644 --- a/src/data/arena.rs +++ b/src/data/arena.rs @@ -19,16 +19,16 @@ use std::vec; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub struct Arena<T> { items: Vec<Entry<T>>, - generation: u64, - free_list_head: Option<usize>, + generation: u32, + free_list_head: Option<u32>, len: usize, } #[derive(Clone, Debug)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] enum Entry<T> { - Free { next_free: Option<usize> }, - Occupied { generation: u64, value: T }, + Free { next_free: Option<u32> }, + Occupied { generation: u32, value: T }, } /// An index (and generation) into an `Arena`. @@ -48,17 +48,17 @@ enum Entry<T> { #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub struct Index { - index: usize, - generation: u64, + index: u32, + generation: u32, } impl IndexedData for Index { fn default() -> Self { - Self::from_raw_parts(crate::INVALID_USIZE, crate::INVALID_U64) + Self::from_raw_parts(crate::INVALID_U32, crate::INVALID_U32) } fn index(&self) -> usize { - self.into_raw_parts().0 + self.into_raw_parts().0 as usize } } @@ -70,7 +70,7 @@ impl Index { /// /// Providing arbitrary values will lead to malformed indices and ultimately /// panics. - pub fn from_raw_parts(a: usize, b: u64) -> Index { + pub fn from_raw_parts(a: u32, b: u32) -> Index { Index { index: a, generation: b, @@ -84,7 +84,7 @@ impl Index { /// `Index` like `pub struct MyIdentifier(Index);`. However, for external /// types whose definition you can't customize, but which you can construct /// instances of, this method can be useful. - pub fn into_raw_parts(self) -> (usize, u64) { + pub fn into_raw_parts(self) -> (u32, u32) { (self.index, self.generation) } } @@ -161,7 +161,7 @@ impl<T> Arena<T> { pub fn clear(&mut self) { self.items.clear(); - let end = self.items.capacity(); + let end = self.items.capacity() as u32; self.items.extend((0..end).map(|i| { if i == end - 1 { Entry::Free { next_free: None } @@ -206,7 +206,7 @@ impl<T> Arena<T> { match self.try_alloc_next_index() { None => Err(value), Some(index) => { - self.items[index.index] = Entry::Occupied { + self.items[index.index as usize] = Entry::Occupied { generation: self.generation, value, }; @@ -247,7 +247,7 @@ impl<T> Arena<T> { match self.try_alloc_next_index() { None => Err(create), Some(index) => { - self.items[index.index] = Entry::Occupied { + self.items[index.index as usize] = Entry::Occupied { generation: self.generation, value: create(index), }; @@ -260,13 +260,13 @@ impl<T> Arena<T> { fn try_alloc_next_index(&mut self) -> Option<Index> { match self.free_list_head { None => None, - Some(i) => match self.items[i] { + Some(i) => match self.items[i as usize] { Entry::Occupied { .. } => panic!("corrupt free list"), Entry::Free { next_free } => { self.free_list_head = next_free; self.len += 1; Some(Index { - index: i, + index: i as u32, generation: self.generation, }) } @@ -355,14 +355,14 @@ impl<T> Arena<T> { /// assert_eq!(arena.remove(idx), None); /// ``` pub fn remove(&mut self, i: Index) -> Option<T> { - if i.index >= self.items.len() { + if i.index >= self.items.len() as u32 { return None; } - match self.items[i.index] { + match self.items[i.index as usize] { Entry::Occupied { generation, .. } if i.generation == generation => { let entry = mem::replace( - &mut self.items[i.index], + &mut self.items[i.index as usize], Entry::Free { next_free: self.free_list_head, }, @@ -402,8 +402,8 @@ impl<T> Arena<T> { /// assert!(crew_members.next().is_none()); /// ``` pub fn retain(&mut self, mut predicate: impl FnMut(Index, &mut T) -> bool) { - for i in 0..self.capacity() { - let remove = match &mut self.items[i] { + for i in 0..self.capacity() as u32 { + let remove = match &mut self.items[i as usize] { Entry::Occupied { generation, value } => { let index = Index { index: i, @@ -462,7 +462,7 @@ impl<T> Arena<T> { /// assert!(arena.get(idx).is_none()); /// ``` pub fn get(&self, i: Index) -> Option<&T> { - match self.items.get(i.index) { + match self.items.get(i.index as usize) { Some(Entry::Occupied { generation, value }) if *generation == i.generation => { Some(value) } @@ -488,7 +488,7 @@ impl<T> Arena<T> { /// assert!(arena.get_mut(idx).is_none()); /// ``` pub fn get_mut(&mut self, i: Index) -> Option<&mut T> { - match self.items.get_mut(i.index) { + match self.items.get_mut(i.index as usize) { Some(Entry::Occupied { generation, value }) if *generation == i.generation => { Some(value) } @@ -526,7 +526,7 @@ impl<T> Arena<T> { /// assert_eq!(arena[idx2], 4); /// ``` pub fn get2_mut(&mut self, i1: Index, i2: Index) -> (Option<&mut T>, Option<&mut T>) { - let len = self.items.len(); + let len = self.items.len() as u32; if i1.index == i2.index { assert!(i1.generation != i2.generation); @@ -544,11 +544,13 @@ impl<T> Arena<T> { } let (raw_item1, raw_item2) = { - let (xs, ys) = self.items.split_at_mut(cmp::max(i1.index, i2.index)); + let (xs, ys) = self + .items + .split_at_mut(cmp::max(i1.index, i2.index) as usize); if i1.index < i2.index { - (&mut xs[i1.index], &mut ys[0]) + (&mut xs[i1.index as usize], &mut ys[0]) } else { - (&mut ys[0], &mut xs[i2.index]) + (&mut ys[0], &mut xs[i2.index as usize]) } }; @@ -666,11 +668,11 @@ impl<T> Arena<T> { } } else { Entry::Free { - next_free: Some(i + 1), + next_free: Some(i as u32 + 1), } } })); - self.free_list_head = Some(start); + self.free_list_head = Some(start as u32); } /// Iterate over shared references to the elements in this arena. @@ -774,7 +776,7 @@ impl<T> Arena<T> { value, Index { generation: *generation, - index: i, + index: i as u32, }, )), _ => None, @@ -797,7 +799,7 @@ impl<T> Arena<T> { value, Index { generation: *generation, - index: i, + index: i as u32, }, )), _ => None, @@ -941,7 +943,10 @@ impl<'a, T> Iterator for Iter<'a, T> { }, )) => { self.len -= 1; - let idx = Index { index, generation }; + let idx = Index { + index: index as u32, + generation, + }; return Some((idx, value)); } None => { @@ -970,7 +975,10 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { }, )) => { self.len -= 1; - let idx = Index { index, generation }; + let idx = Index { + index: index as u32, + generation, + }; return Some((idx, value)); } None => { @@ -1039,7 +1047,10 @@ impl<'a, T> Iterator for IterMut<'a, T> { }, )) => { self.len -= 1; - let idx = Index { index, generation }; + let idx = Index { + index: index as u32, + generation, + }; return Some((idx, value)); } None => { @@ -1068,7 +1079,10 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { }, )) => { self.len -= 1; - let idx = Index { index, generation }; + let idx = Index { + index: index as u32, + generation, + }; return Some((idx, value)); } None => { @@ -1126,7 +1140,10 @@ impl<'a, T> Iterator for Drain<'a, T> { match self.inner.next() { Some((_, Entry::Free { .. })) => continue, Some((index, Entry::Occupied { generation, value })) => { - let idx = Index { index, generation }; + let idx = Index { + index: index as u32, + generation, + }; return Some((idx, value)); } None => return None, diff --git a/src/data/coarena.rs b/src/data/coarena.rs index c25cc55..cd64910 100644 --- a/src/data/coarena.rs +++ b/src/data/coarena.rs @@ -4,7 +4,7 @@ use crate::data::arena::Index; #[derive(Clone, Debug)] /// A container for data associated to item existing into another Arena. pub struct Coarena<T> { - data: Vec<(u64, T)>, + data: Vec<(u32, T)>, } impl<T> Coarena<T> { @@ -17,7 +17,7 @@ impl<T> Coarena<T> { pub fn get(&self, index: Index) -> Option<&T> { let (i, g) = index.into_raw_parts(); self.data - .get(i) + .get(i as usize) .and_then(|(gg, t)| if g == *gg { Some(t) } else { None }) } @@ -25,7 +25,7 @@ impl<T> Coarena<T> { pub fn get_mut(&mut self, index: Index) -> Option<&mut T> { let (i, g) = index.into_raw_parts(); self.data - .get_mut(i) + .get_mut(i as usize) .and_then(|(gg, t)| if g == *gg { Some(t) } else { None }) } @@ -36,11 +36,11 @@ impl<T> Coarena<T> { { let (i1, g1) = a.into_raw_parts(); - if self.data.len() <= i1 { - self.data.resize(i1 + 1, (u32::MAX as u64, T::default())); + if self.data.len() <= i1 as usize { + self.data.resize(i1 as usize + 1, (u32::MAX, T::default())); } - self.data[i1] = (g1, value); + self.data[i1 as usize] = (g1, value); } /// Ensure that elements at the two given indices exist in this coarena, and return their reference. @@ -56,20 +56,22 @@ impl<T> Coarena<T> { assert_ne!(i1, i2, "Cannot index the same object twice."); let (elt1, elt2) = if i1 > i2 { - if self.data.len() <= i1 { - self.data.resize(i1 + 1, (u32::MAX as u64, default.clone())); + if self.data.len() <= i1 as usize { + self.data + .resize(i1 as usize + 1, (u32::MAX, default.clone())); } - let (left, right) = self.data.split_at_mut(i1); - (&mut right[0], &mut left[i2]) + let (left, right) = self.data.split_at_mut(i1 as usize); + (&mut right[0], &mut left[i2 as usize]) } else { // i2 > i1 - if self.data.len() <= i2 { - self.data.resize(i2 + 1, (u32::MAX as u64, default.clone())); + if self.data.len() <= i2 as usize { + self.data + .resize(i2 as usize + 1, (u32::MAX, default.clone())); } - let (left, right) = self.data.split_at_mut(i2); - (&mut left[i1], &mut right[0]) + let (left, right) = self.data.split_at_mut(i2 as usize); + (&mut left[i1 as usize], &mut right[0]) }; if elt1.0 != g1 { diff --git a/src/data/component_set.rs b/src/data/component_set.rs new file mode 100644 index 0000000..76e076a --- /dev/null +++ b/src/data/component_set.rs @@ -0,0 +1,106 @@ +use crate::data::Index; + +// TODO ECS: use this to handle optional components properly. +// pub trait OptionalComponentSet<T> { +// fn get(&self, handle: Index) -> Option<&T>; +// } + +pub trait ComponentSetOption<T> { + fn get(&self, handle: Index) -> Option<&T>; +} + +pub trait ComponentSet<T>: ComponentSetOption<T> { + fn size_hint(&self) -> usize; + // TODO ECS: remove this, its only needed by the query pipeline update + // which should only take the modified colliders into account. + fn for_each(&self, f: impl FnMut(Index, &T)); + fn index(&self, handle: Index) -> &T { + self.get(handle).unwrap() + } +} + +pub trait ComponentSetMut<T>: ComponentSet<T> { + fn map_mut_internal<Result>( + &mut self, + handle: crate::data::Index, + f: impl FnOnce(&mut T) -> Result, + ) -> Option<Result>; + fn set_internal(&mut self, handle: crate::data::Index, val: T); +} + +pub trait BundleSet<'a, T> { + fn index_bundle(&'a self, handle: Index) -> T; +} + +impl<'a, T, A, B> BundleSet<'a, (&'a A, &'a B)> for T +where + T: ComponentSet<A> + ComponentSet<B>, +{ + #[inline(always)] + fn index_bundle(&'a self, handle: Index) -> (&'a A, &'a B) { + (self.index(handle), self.index(handle)) + } +} + +impl<'a, T, A, B, C> BundleSet<'a, (&'a A, &'a B, &'a C)> for T +where + T: ComponentSet<A> + ComponentSet<B> + ComponentSet<C>, +{ + #[inline(always)] + fn index_bundle(&'a self, handle: Index) -> (&'a A, &'a B, &'a C) { + (self.index(handle), self.index(handle), self.index(handle)) + } +} + +impl<'a, T, A, B, C, D> BundleSet<'a, (&'a A, &'a B, &'a C, &'a D)> for T +where + T: ComponentSet<A> + ComponentSet<B> + ComponentSet<C> + ComponentSet<D>, +{ + #[inline(always)] + fn index_bundle(&'a self, handle: Index) -> (&'a A, &'a B, &'a C, &'a D) { + ( + self.index(handle), + self.index(handle), + self.index(handle), + self.index(handle), + ) + } +} + +impl<'a, T, A, B, C, D, E> BundleSet<'a, (&'a A, &'a B, &'a C, &'a D, &'a E)> for T +where + T: ComponentSet<A> + ComponentSet<B> + ComponentSet<C> + ComponentSet<D> + ComponentSet<E>, +{ + #[inline(always)] + fn index_bundle(&'a self, handle: Index) -> (&'a A, &'a B, &'a C, &'a D, &'a E) { + ( + self.index(handle), + self.index(handle), + self.index(handle), + self.index(handle), + self.index(handle), + ) + } +} + +impl<'a, T, A, B, C, D, E, F> BundleSet<'a, (&'a A, &'a B, &'a C, &'a D, &'a E, &'a F)> for T +where + T: ComponentSet<A> + + ComponentSet<B> + + ComponentSet<C> + + ComponentSet<D> + + ComponentSet<E> + + ComponentSet<F>, +{ + #[inline(always)] + fn index_bundle(&'a self, handle: Index) -> (&'a A, &'a B, &'a C, &'a D, &'a E, &'a F) { + ( + self.index(handle), + self.index(handle), + self.index(handle), + self.index(handle), + self.index(handle), + self.index(handle), + ) + } +} diff --git a/src/data/mod.rs b/src/data/mod.rs index 7c49314..f20e433 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -1,8 +1,11 @@ //! Data structures modified with guaranteed deterministic behavior after deserialization. +pub use self::arena::{Arena, Index}; pub use self::coarena::Coarena; +pub use self::component_set::{BundleSet, ComponentSet, ComponentSetMut, ComponentSetOption}; pub mod arena; mod coarena; +mod component_set; pub(crate) mod graph; pub mod pubsub; |
