1use super::{ManagedSlice as Slice};
7
8#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
14pub struct Slot {
15 generation_id: GenerationOrFreelink,
23}
24
25pub struct SlotMap<'a, T> {
52 elements: Slice<'a, T>,
55 slots: Partial<'a, Slot>,
59 generation: Generation,
62 free_top: usize,
65 indices: IndexComputer,
67}
68
69struct Partial<'a, T> {
71 slice: Slice<'a, T>,
72 next_idx: usize,
73}
74
75#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
81pub struct Key {
82 idx: usize,
83 generation: Generation,
84}
85
86#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
87struct GenerationOrFreelink(isize);
88
89#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
91struct FreeIndex(usize);
92
93#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
97struct Generation(isize);
98
99#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
107struct Offset(isize);
108
109struct IndexComputer(usize);
111
112impl<T> SlotMap<'_, T> {
113 pub fn get(&self, index: Key) -> Option<&T> {
115 let slot_generation = self.slots
116 .get(index.idx)?
117 .generation_id
118 .generation().ok()?;
119
120 if slot_generation != index.generation {
121 return None;
122 }
123
124 self.elements.get(index.idx)
125 }
126
127 pub fn get_mut(&mut self, index: Key) -> Option<&mut T> {
129 let slot_generation = self.slots
130 .get(index.idx)?
131 .generation_id
132 .generation().ok()?;
133
134 if slot_generation != index.generation {
135 return None;
136 }
137
138 self.elements.get_mut(index.idx)
139 }
140
141 pub fn reserve(&mut self) -> Option<(Key, &mut T)> {
147 let index = self.next_free_slot()?;
148 let slot = self.slots.get_mut(index.0).unwrap();
149 let element = &mut self.elements[index.0];
150
151 let offset = slot.generation_id
152 .free_link()
153 .expect("Free link should be free");
154 slot.generation_id = self.generation.into();
155 let key = Key {
156 idx: index.0,
157 generation: self.generation,
158 };
159
160 self.free_top = self.indices.free_list_next(index, offset);
161 self.generation.advance();
162 Some((key, element))
163 }
164
165 pub fn insert(&mut self, value: T) -> Option<Key> {
171 let (index, element) = self.reserve()?;
173 *element = value;
174 Some(index)
175 }
176
177 pub fn remove(&mut self, index: Key) -> Option<&mut T> {
183 if self.get(index).is_none() {
184 return None
185 }
186
187 let free = FreeIndex(index.idx);
189 let slot = self.slots.get_mut(index.idx).unwrap();
190 assert!(slot.generation_id.generation().is_ok());
191
192 let offset = self.indices.free_list_offset(free, self.free_top);
193 slot.generation_id = offset.into();
194 self.free_top = index.idx;
195
196 Some(&mut self.elements[index.idx])
197 }
198
199 fn next_free_slot(&mut self) -> Option<FreeIndex> {
201 let free = match self.slots.get_mut(self.free_top) {
208 Some(_) => {
210 let _= self.elements.get_mut(self.free_top)?;
212 FreeIndex(self.free_top)
213 },
214 None => { let new_index = self.slots.len();
218 let _ = self.elements.get_mut(new_index)?;
220
221 let free_slot = self.slots.try_reserve()?;
222 let free_index = FreeIndex(new_index);
223 let new_top = new_index.checked_add(1).unwrap();
225
226 let offset = self.indices.free_list_offset(free_index, new_top);
227 free_slot.generation_id = offset.into();
228 self.free_top = free_index.0;
229
230 free_index
231 }
232 };
233
234
235 Some(free)
237 }
238}
239
240impl<'a, T> SlotMap<'a, T> {
241 pub fn new(elements: Slice<'a, T>, slots: Slice<'a, Slot>) -> Self {
245 let capacity = elements.len().min(slots.len());
246 SlotMap {
247 elements,
248 slots: Partial {
249 slice: slots,
250 next_idx: 0,
251 },
252 generation: Generation::default(),
253 free_top: 0,
254 indices: IndexComputer::from_capacity(capacity),
255 }
256 }
257}
258
259impl<'a, T> Partial<'a, T> {
260 fn get(&self, idx: usize) -> Option<&T> {
261 if idx >= self.next_idx {
262 None
263 } else {
264 Some(&self.slice[idx])
265 }
266 }
267
268 fn get_mut(&mut self, idx: usize) -> Option<&mut T> {
269 if idx >= self.next_idx {
270 None
271 } else {
272 Some(&mut self.slice[idx])
273 }
274 }
275
276 fn len(&self) -> usize {
277 self.next_idx
278 }
279
280 fn try_reserve(&mut self) -> Option<&mut T> {
281 if self.next_idx == self.slice.len() {
282 None
283 } else {
284 let idx = self.next_idx;
285 self.next_idx += 1;
286 Some(&mut self.slice[idx])
287 }
288 }
289}
290
291impl GenerationOrFreelink {
292 pub(crate) fn free_link(self) -> Result<Offset, Generation> {
293 if self.0 > 0 {
294 Err(Generation(self.0))
295 } else {
296 Ok(Offset(self.0))
297 }
298 }
299
300 pub(crate) fn generation(self) -> Result<Generation, Offset> {
301 match self.free_link() {
302 Ok(offset) => Err(offset),
303 Err(generation) => Ok(generation),
304 }
305 }
306}
307
308impl IndexComputer {
309 pub(crate) fn from_capacity(capacity: usize) -> Self {
310 assert!(capacity < isize::max_value() as usize);
311 IndexComputer(capacity)
312 }
313
314 fn free_list_next(&self, FreeIndex(base): FreeIndex, offset: Offset)
319 -> usize
320 {
321 let capacity = self.0;
322 let offset = offset.int_offset();
323
324 assert!(base < capacity);
325 assert!(offset <= capacity);
326 let base = base + 1;
327
328 if capacity - offset >= base {
329 offset + base } else {
331 offset
334 .wrapping_add(base)
335 .wrapping_sub(capacity + 1)
336 }
337 }
338
339 fn free_list_offset(&self, FreeIndex(base): FreeIndex, to: usize)
345 -> Offset
346 {
347 let capacity = self.0;
348
349 assert!(base != to, "Cant offset element to itself");
350 assert!(base < capacity, "Should never have to offset the end-of-list marker");
351 assert!(to <= capacity, "Can only offset to the end-of-list marker");
352 let base = base + 1;
353
354 Offset::from_int_offset(if base <= to {
355 to - base
356 } else {
357 to
359 .wrapping_add(capacity + 1)
360 .wrapping_sub(base)
361 })
362 }
363}
364
365impl Generation {
366 pub(crate) fn advance(&mut self) {
367 assert!(self.0 > 0);
368 self.0 = self.0.wrapping_add(1).max(1)
369 }
370}
371
372impl Offset {
373 pub(crate) fn from_int_offset(offset: usize) -> Self {
374 assert!(offset < isize::max_value() as usize);
375 Offset((offset as isize).checked_neg().unwrap())
376 }
377
378 pub(crate) fn int_offset(self) -> usize {
379 self.0.checked_neg().unwrap() as usize
380 }
381}
382
383impl Default for Generation {
384 fn default() -> Self {
385 Generation(1)
386 }
387}
388
389impl From<Generation> for GenerationOrFreelink {
390 fn from(gen: Generation) -> GenerationOrFreelink {
391 GenerationOrFreelink(gen.0)
392 }
393}
394
395impl From<Offset> for GenerationOrFreelink {
396 fn from(offset: Offset) -> GenerationOrFreelink {
397 GenerationOrFreelink(offset.0)
398 }
399}
400
401#[cfg(test)]
402mod tests {
403 use super::*;
404 use crate::slice::ManagedSlice as Slice;
405
406 #[test]
407 fn simple() {
408 let mut elements = [0u32; 2];
409 let mut slots = [Slot::default(); 2];
410
411 let mut map = SlotMap::new(
412 Slice::Borrowed(&mut elements[..]),
413 Slice::Borrowed(&mut slots[..]));
414 let key42 = map.insert(42).unwrap();
415 let keylo = map.insert('K' as _).unwrap();
416
417 assert_eq!(map.insert(0x9999), None);
418 assert_eq!(map.get(key42).cloned(), Some(42));
419 assert_eq!(map.get(keylo).cloned(), Some('K' as _));
420
421 assert!(map.remove(key42).is_some());
422 assert_eq!(map.get(key42), None);
423
424 let lastkey = map.insert(0x9999).unwrap();
425 assert_eq!(map.get(lastkey).cloned(), Some(0x9999));
426
427 *map.remove(keylo).unwrap() = 0;
428 assert_eq!(map.get(lastkey).cloned(), Some(0x9999));
429 assert!(map.remove(lastkey).is_some());
430 }
431
432 #[test]
433 fn retained() {
434 let mut elements = [0u32; 1];
435 let mut slots = [Slot::default(); 1];
436
437 let mut map = SlotMap::new(
438 Slice::Borrowed(&mut elements[..]),
439 Slice::Borrowed(&mut slots[..]));
440 let key = map.insert(0xde).unwrap();
441 map.remove(key).unwrap();
442 assert_eq!(map.get(key), None);
443
444 let new_key = map.insert(0xad).unwrap();
445
446 assert_eq!(map.get(key), None);
447 assert_eq!(map.get(new_key).cloned(), Some(0xad));
448
449 assert_eq!(map.remove(key), None);
450 map.remove(new_key).unwrap();
451
452 assert_eq!(map.get(key), None);
453 assert_eq!(map.get(new_key), None);
454 }
455
456 #[test]
457 fn non_simple_free_list() {
458 let mut elements = [0u32; 3];
460 let mut slots = [Slot::default(); 3];
461
462 let mut map = SlotMap::new(
463 Slice::Borrowed(&mut elements[..]),
464 Slice::Borrowed(&mut slots[..]));
465
466 let key0 = map.insert(0).unwrap();
467 let key1 = map.insert(1).unwrap();
468 let key2 = map.insert(2).unwrap();
469
470 *map.remove(key1).unwrap() = 0xF;
471 assert_eq!(map.free_top, 1);
472 assert_eq!(map.get(key0).cloned(), Some(0));
473 assert_eq!(map.get(key2).cloned(), Some(2));
474
475 *map.remove(key2).unwrap() = 0xF;
476 assert_eq!(map.free_top, 2);
477 assert_eq!(map.get(key0).cloned(), Some(0));
478
479 *map.remove(key0).unwrap() = 0xF;
480 assert_eq!(map.free_top, 0);
481
482 let key0 = map.insert(0).unwrap();
483 assert_eq!(map.free_top, 2);
484 let key1 = map.insert(1).unwrap();
485 let key2 = map.insert(2).unwrap();
486 assert_eq!(map.get(key0).cloned(), Some(0));
487 assert_eq!(map.get(key1).cloned(), Some(1));
488 assert_eq!(map.get(key2).cloned(), Some(2));
489 }
490}