Skip to main content

goggles/
storage.rs

1use std::{
2    cell::UnsafeCell,
3    collections::HashMap,
4    mem::{self, MaybeUninit},
5    ptr,
6};
7
8use crate::join::Index;
9
10/// A trait for storing components in memory based on low valued indexes.
11///
12/// Is not required to keep track of whether the component is present or not for a given index, it
13/// is up to the user of a `RawStorage` to keep track of this.
14///
15/// Because of this, a type that implements `RawStorage` is allowed to leak *all* component values
16/// on drop.  In order to prevent this, the storage must have only empty indexes at the time of
17/// drop.
18pub trait RawStorage {
19    type Item;
20
21    /// Return a reference to the component at the given index.
22    ///
23    /// You *must* only call `get` with index values that are non-empty (have been previously had
24    /// components inserted with `insert`).
25    unsafe fn get(&self, index: Index) -> &Self::Item;
26
27    /// Return a mutable reference to the component at the given index.
28    ///
29    /// You *must* only call `get_mut` with index values that are non-empty (have been previously
30    /// had components inserted with `insert`).
31    ///
32    /// Returns a *mutable* reference to the previously inserted component.  You must follow Rust's
33    /// aliasing rules here, so you must not call this method if there is any other live reference
34    /// to the same component.
35    unsafe fn get_mut(&self, index: Index) -> &mut Self::Item;
36
37    /// Insert a new component value in the given index.
38    ///
39    /// You must only call `insert` on indexes that are empty.  All indexes start empty, but become
40    /// non-empty once `insert` is called on them.
41    unsafe fn insert(&mut self, index: Index, value: Self::Item);
42
43    /// Remove a component previously inserted in the given index.
44    ///
45    /// You must only call `remove` on a non-empty index (after you have inserted a value with
46    /// `insert`).  After calling `remove` the index becomes empty.
47    unsafe fn remove(&mut self, index: Index) -> Self::Item;
48}
49
50/// Trait for storages that hold their populated values densely in a contiguous slice, enabling
51/// faster access to populated values.  The slice is not guaranteed to be in any particular order.
52pub trait DenseStorage: RawStorage {
53    fn as_slice(&self) -> &[Self::Item];
54    fn as_mut_slice(&mut self) -> &mut [Self::Item];
55}
56
57pub struct VecStorage<T>(Vec<UnsafeCell<MaybeUninit<T>>>);
58
59unsafe impl<T: Send> Send for VecStorage<T> {}
60unsafe impl<T: Sync> Sync for VecStorage<T> {}
61
62impl<T> Default for VecStorage<T> {
63    fn default() -> Self {
64        Self(Vec::new())
65    }
66}
67
68impl<T> RawStorage for VecStorage<T> {
69    type Item = T;
70
71    unsafe fn get(&self, index: Index) -> &T {
72        &*(*self.0.get_unchecked(index as usize).get()).as_ptr()
73    }
74
75    unsafe fn get_mut(&self, index: Index) -> &mut T {
76        &mut *(*self.0.get_unchecked(index as usize).get()).as_mut_ptr()
77    }
78
79    unsafe fn insert(&mut self, index: Index, c: T) {
80        let index = index as usize;
81        if self.0.len() <= index {
82            let delta = index + 1 - self.0.len();
83            self.0.reserve(delta);
84            self.0.set_len(index + 1);
85        }
86        *self.0.get_unchecked_mut(index as usize) = UnsafeCell::new(MaybeUninit::new(c));
87    }
88
89    unsafe fn remove(&mut self, index: Index) -> T {
90        ptr::read((*self.0.get_unchecked(index as usize).get()).as_mut_ptr())
91    }
92}
93
94pub struct DenseVecStorage<T> {
95    data: Vec<MaybeUninit<Index>>,
96    values: Vec<UnsafeCell<T>>,
97    indexes: Vec<Index>,
98}
99
100unsafe impl<T: Send> Send for DenseVecStorage<T> {}
101unsafe impl<T: Sync> Sync for DenseVecStorage<T> {}
102
103impl<T> Default for DenseVecStorage<T> {
104    fn default() -> Self {
105        Self {
106            data: Vec::new(),
107            values: Vec::new(),
108            indexes: Vec::new(),
109        }
110    }
111}
112
113impl<T> RawStorage for DenseVecStorage<T> {
114    type Item = T;
115
116    unsafe fn get(&self, index: Index) -> &T {
117        let dind = *self.data.get_unchecked(index as usize).as_ptr();
118        &*self.values.get_unchecked(dind as usize).get()
119    }
120
121    unsafe fn get_mut(&self, index: Index) -> &mut T {
122        let dind = *self.data.get_unchecked(index as usize).as_ptr();
123        &mut *self.values.get_unchecked(dind as usize).get()
124    }
125
126    unsafe fn insert(&mut self, index: Index, c: T) {
127        if self.data.len() <= index as usize {
128            let delta = index as usize + 1 - self.data.len();
129            self.data.reserve(delta);
130            self.data.set_len(index as usize + 1);
131        }
132        self.indexes.reserve(1);
133        self.values.reserve(1);
134
135        self.data
136            .get_unchecked_mut(index as usize)
137            .as_mut_ptr()
138            .write(self.values.len() as Index);
139        self.indexes.push(index);
140        self.values.push(UnsafeCell::new(c));
141    }
142
143    unsafe fn remove(&mut self, index: Index) -> T {
144        let dind = *self.data.get_unchecked(index as usize).as_ptr();
145        let last_index = *self.indexes.get_unchecked(self.indexes.len() - 1);
146        self.data
147            .get_unchecked_mut(last_index as usize)
148            .as_mut_ptr()
149            .write(dind);
150        self.indexes.swap_remove(dind as usize);
151        self.values.swap_remove(dind as usize).into_inner()
152    }
153}
154
155impl<T> DenseStorage for DenseVecStorage<T> {
156    fn as_slice(&self) -> &[Self::Item] {
157        unsafe { mem::transmute::<&[UnsafeCell<T>], &[T]>(&self.values) }
158    }
159
160    fn as_mut_slice(&mut self) -> &mut [Self::Item] {
161        unsafe { mem::transmute::<&mut [UnsafeCell<T>], &mut [T]>(&mut self.values) }
162    }
163}
164
165pub struct HashMapStorage<T>(HashMap<Index, UnsafeCell<T>>);
166
167unsafe impl<T: Send> Send for HashMapStorage<T> {}
168unsafe impl<T: Sync> Sync for HashMapStorage<T> {}
169
170impl<T> Default for HashMapStorage<T> {
171    fn default() -> Self {
172        Self(HashMap::default())
173    }
174}
175
176impl<T> RawStorage for HashMapStorage<T> {
177    type Item = T;
178
179    unsafe fn get(&self, index: Index) -> &T {
180        &*self.0.get(&index).unwrap().get()
181    }
182
183    unsafe fn get_mut(&self, index: Index) -> &mut T {
184        &mut *self.0.get(&index).unwrap().get()
185    }
186
187    unsafe fn insert(&mut self, index: Index, v: T) {
188        self.0.insert(index, UnsafeCell::new(v));
189    }
190
191    unsafe fn remove(&mut self, index: Index) -> T {
192        self.0.remove(&index).unwrap().into_inner()
193    }
194}