use rayon::prelude::*; use std::{ cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}, fmt, hash, marker::PhantomData, ops::{Index, IndexMut}, }; // NOTE: We use u64 to make sure we are consistent across all machines. We // assume that usize fits into 8 bytes. pub struct Id(u64, PhantomData); impl Id { pub fn id(&self) -> u64 { self.0 } } impl Copy for Id {} impl Clone for Id { fn clone(&self) -> Self { Self(self.0, PhantomData) } } impl Eq for Id {} impl PartialEq for Id { fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } impl Ord for Id { fn cmp(&self, other: &Self) -> Ordering { self.0.cmp(&(other.0)) } } impl PartialOrd for Id { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl fmt::Debug for Id { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Id<{}>({})", std::any::type_name::(), self.0) } } impl hash::Hash for Id { fn hash(&self, h: &mut H) { self.0.hash(h); } } pub struct Store { items: Vec, } impl Default for Store { fn default() -> Self { Self { items: Vec::new() } } } impl Store { pub fn get(&self, id: Id) -> &T { // NOTE: Safe conversion, because it came from usize. self.items.get(id.0 as usize).unwrap() } pub fn get_mut(&mut self, id: Id) -> &mut T { // NOTE: Safe conversion, because it came from usize. self.items.get_mut(id.0 as usize).unwrap() } pub fn ids(&self) -> impl Iterator> { (0..self.items.len()).map(|i| Id(i as u64, PhantomData)) } pub fn values(&self) -> impl ExactSizeIterator { self.items.iter() } pub fn values_mut(&mut self) -> impl ExactSizeIterator { self.items.iter_mut() } pub fn iter(&self) -> impl Iterator, &T)> { self.ids().zip(self.values()) } pub fn iter_mut(&mut self) -> impl Iterator, &mut T)> { self.ids().zip(self.values_mut()) } pub fn insert(&mut self, item: T) -> Id { // NOTE: Assumes usize fits into 8 bytes. let id = Id(self.items.len() as u64, PhantomData); self.items.push(item); id } pub fn recreate_id(&self, i: u64) -> Option> { if i as usize >= self.items.len() { None } else { Some(Id::(i, PhantomData)) } } } impl Store { pub fn par_iter_mut(&mut self) -> impl ParallelIterator, &mut T)> { self.items .par_iter_mut() .enumerate() .map(|(idx, obj)| (Id(idx as u64, PhantomData), obj)) } } impl Index> for Store { type Output = T; fn index(&self, id: Id) -> &Self::Output { self.get(id) } } impl IndexMut> for Store { fn index_mut(&mut self, id: Id) -> &mut Self::Output { self.get_mut(id) } }