gen_value/
unmanaged.rs

1// Copyright 2023 Bryant Luk
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! `Vec` indexed with externally managed generational indexes.
10
11use core::{cmp::Ordering, marker::PhantomData};
12
13#[cfg(all(feature = "alloc", not(feature = "std")))]
14use alloc::vec::Vec;
15#[cfg(feature = "std")]
16use std::vec::Vec;
17
18use crate::{Error, Incrementable};
19
20/// `Vec` indexed with externally managed generational indexes.
21///
22/// `UnmanagedGenVec` does not manage its own indexes. An external source must
23/// allocate and deallocate indexes with generations appropriately.
24///
25/// If a single `Vec` with generational indexes is required, then using
26/// [`GenVec`][crate::vec::GenVec] is useful. If generational indexes must be
27/// allocated and deallocated externally or if multiple vectors are required,
28/// then the [`Allocator`][crate::index::Allocator] and `UnmanagedGenVec` may be
29/// more useful.
30///
31/// # Safety
32///
33/// The generation at an index in the inner `Vec` should always be greater than or
34/// equal to any generational index's generation for the same index.
35///
36/// If the generation has a maximum value (e.g. `u8::MAX`), then the maximum value
37/// should serve as a tombstone to indicate that the index cannot be used.
38/// Any generational index with the maximum generation should never
39/// be used for any method except [`set_next_gen`][UnmanagedGenVec::set_next_gen].
40///
41/// # Type Parameters
42///
43/// ## `T`
44///
45/// `T` is the element value type like the `T` in `Vec<T>`.
46///
47/// ## `G`
48///
49/// `G` is the generation type. `G` is usually a type like [u16] or [u32].
50/// By default, G is a [usize].
51///
52/// Generation types must implement:
53///
54/// * [`PartialOrd`]
55/// * [`Default`]
56///
57/// The range of values for `G` determines how many generations a single index
58/// can be used. Assume a [u8] is used and a single index is allocated and
59/// deallocated 255 times. After the 255th allocation, the index will never be
60/// allocated again. For [`GenVec`][crate::vec::GenVec], an index which will
61/// never be re-used is essentially equivalent to wasted memory which will not
62/// be reclaimed.
63///
64/// Note that for a [u8], the maximum value (255) serves as a tombstone marker
65/// indicating that the index can no longer be used (otherwise a generational
66/// index with generation 255 could always access the value).
67///
68/// Assuming a single index is allocated and deallocated every second, a [u16]
69/// would take (2^16 - 1) seconds to exhaust an index which is roughly 18 hours. A
70/// [u32] would take (2^32 - 1) seconds which is more than 136 years.
71///
72/// ## `I`
73///
74/// `I` is the index type required in most functions. `I` is turned into a
75/// [usize] to index into the inner `Vec`. By default, `I` is a [usize].
76///
77/// Index types must implement:
78///
79/// * `Into<usize>`
80///
81/// The range of values for `I` determines the maximum limit on how many
82/// concurrent entities may exist. If a [u8] is used, a maximum of `256`
83/// values exist at any point in time.
84///
85/// ## `GenIndex`
86///
87/// `GenIndex` is the type which the generational index should be. A tuple
88/// like `(I, G)` can be used or a custom type. By default, `(I, G)` is used.
89///
90/// The generational index type is generally treated like an opaque identifier.
91/// While a tuple is useful, a custom type may be desired so a generational
92/// index is only used with collections which take the custom type.
93///
94/// `GenIndex` types must implement:
95///
96/// * `Into<(I, G)> for GenIndex`
97#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
98#[allow(clippy::module_name_repetitions)]
99pub struct UnmanagedGenVec<T, G = usize, I = usize, GenIndex = (I, G)> {
100    inner: Vec<(G, T)>,
101    index_ty: PhantomData<I>,
102    gen_index_ty: PhantomData<GenIndex>,
103}
104
105impl<T, G, I, GenIndex> UnmanagedGenVec<T, G, I, GenIndex> {
106    /// Constructs a new inner [`Vec`].
107    ///
108    /// See [`Vec::new`] for additional information.
109    #[must_use]
110    pub fn new() -> Self {
111        Self {
112            inner: Vec::new(),
113            index_ty: PhantomData,
114            gen_index_ty: PhantomData,
115        }
116    }
117
118    /// Constructs an inner [`Vec`] with the given capacity.
119    ///
120    /// See [`Vec::with_capacity`] for additional information.
121    #[must_use]
122    pub fn with_capacity(capacity: usize) -> Self {
123        Self {
124            inner: Vec::with_capacity(capacity),
125            index_ty: PhantomData,
126            gen_index_ty: PhantomData,
127        }
128    }
129
130    /// Returns the length of the inner [`Vec`].
131    ///
132    /// See [`Vec::len`] for additional information.
133    #[must_use]
134    #[inline]
135    pub fn len(&self) -> usize {
136        self.inner.len()
137    }
138
139    /// Returns true if the innner [`Vec`] is empty.
140    ///
141    /// See [`Vec::is_empty`] for additional information.
142    #[must_use]
143    #[inline]
144    pub fn is_empty(&self) -> bool {
145        self.inner.is_empty()
146    }
147
148    /// Returns the capacity of the inner [`Vec`].
149    ///
150    /// See [`Vec::capacity`] for additional information.
151    #[must_use]
152    #[inline]
153    pub fn capacity(&self) -> usize {
154        self.inner.capacity()
155    }
156
157    /// Reserves additional capacity of the inner [`Vec`].
158    ///
159    /// See [`Vec::reserve`] for additional information.
160    #[inline]
161    pub fn reserve(&mut self, additional: usize) {
162        self.inner.reserve(additional);
163    }
164
165    /// Reserves additional capacity of the inner [`Vec`].
166    ///
167    /// See [`Vec::reserve_exact`] for additional information.
168    #[inline]
169    pub fn reserve_exact(&mut self, additional: usize) {
170        self.inner.reserve_exact(additional);
171    }
172}
173
174impl<T, G, I, GenIndex> Default for UnmanagedGenVec<T, G, I, GenIndex> {
175    fn default() -> Self {
176        Self {
177            inner: Vec::default(),
178            index_ty: PhantomData,
179            gen_index_ty: PhantomData,
180        }
181    }
182}
183
184impl<T, G, I, GenIndex> UnmanagedGenVec<T, G, I, GenIndex> {
185    /// Pushes the default generation and value to the end of the inner [`Vec`].
186    ///
187    /// See [`Vec::push`] for additional information.
188    #[inline]
189    pub fn push(&mut self, value: T)
190    where
191        G: Default,
192    {
193        self.inner.push((G::default(), value));
194    }
195
196    /// Pushes a generation and value to the end of the inner [`Vec`].
197    ///
198    /// See [`Vec::push`] for additional information.
199    #[inline]
200    pub fn push_with_gen(&mut self, generation: G, value: T) {
201        self.inner.push((generation, value));
202    }
203
204    /// Returns true if an element exists for the generational index.
205    #[must_use]
206    #[inline]
207    pub fn contains_index(&self, gen_index: GenIndex) -> bool
208    where
209        GenIndex: Into<(I, G)>,
210        I: Into<usize>,
211        G: PartialEq,
212    {
213        self.get(gen_index).is_ok()
214    }
215
216    /// Returns a reference to the element at the given index if the generation matches.
217    ///
218    /// See [`slice::get`] for additional information.
219    ///
220    /// # Errors
221    ///
222    /// Errors are returned if:
223    ///
224    /// * the index is out of bounds
225    /// * the generation of the generational index is not equal to the generation associated with the element
226    pub fn get(&self, gen_index: GenIndex) -> Result<&T, Error>
227    where
228        GenIndex: Into<(I, G)>,
229        I: Into<usize>,
230        G: PartialEq,
231    {
232        let gen_index = gen_index.into();
233        self.inner
234            .get(gen_index.0.into())
235            .ok_or_else(Error::index_out_of_bounds)
236            .map(|(gen, elem)| {
237                if gen_index.1 == *gen {
238                    Some(elem)
239                } else {
240                    None
241                }
242            })?
243            .ok_or_else(Error::not_equal_generation)
244    }
245
246    /// Returns a mutable reference to the element at the given index if the generation matches.
247    ///
248    /// See [`slice::get_mut`] for additional information.
249    ///
250    /// # Errors
251    ///
252    /// Errors are returned if:
253    ///
254    /// * the index is out of bounds
255    /// * the generation of the generational index is not equal to the generation associated with the element
256    pub fn get_mut(&mut self, gen_index: GenIndex) -> Result<&mut T, Error>
257    where
258        GenIndex: Into<(I, G)>,
259        I: Into<usize>,
260        G: PartialEq,
261    {
262        let gen_index = gen_index.into();
263        let elem = self
264            .inner
265            .get_mut(gen_index.0.into())
266            .ok_or_else(Error::index_out_of_bounds)?;
267        if elem.0 == gen_index.1 {
268            Ok(&mut elem.1)
269        } else {
270            Err(Error::not_equal_generation())
271        }
272    }
273
274    /// Returns a reference to the element at the given index.
275    ///
276    /// See [`slice::get_unchecked`] for additional information.
277    ///
278    /// # Safety
279    ///
280    /// There is no bounds check and no generation check performed. If the index is out of bounds, undefined behavior will occur.
281    #[inline]
282    #[must_use]
283    pub unsafe fn get_unchecked(&self, index: usize) -> &T {
284        &self.inner.get_unchecked(index).1
285    }
286
287    /// Returns a mutable reference to the element at the given index.
288    ///
289    /// See [`slice::get_unchecked_mut`] for additional information.
290    ///
291    /// # Safety
292    ///
293    /// There is no bounds check and no generation check performed. If the index is out of bounds, undefined behavior will occur.
294    #[inline]
295    #[must_use]
296    pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
297        &mut self.inner.get_unchecked_mut(index).1
298    }
299
300    /// Returns the generation associated with the element at the index.
301    ///
302    /// Returns `None` if the index is out of bounds.
303    #[inline]
304    pub fn get_gen(&self, index: I) -> Option<&G>
305    where
306        I: Into<usize>,
307    {
308        self.inner.get(index.into()).map(|(gen, _value)| gen)
309    }
310
311    fn internal_set(&mut self, index: usize, generation: G, value: T) -> Result<(G, T), Error>
312    where
313        G: PartialOrd,
314    {
315        let elem = self
316            .inner
317            .get_mut(index)
318            .ok_or_else(Error::index_out_of_bounds)?;
319        if elem.0 == generation {
320            let prev_value = core::mem::replace(elem, (generation, value));
321            Ok(prev_value)
322        } else {
323            assert!(
324                generation < elem.0,
325                "generation is greater than generation associated with element"
326            );
327            Err(Error::less_than_existing_generation())
328        }
329    }
330
331    /// Sets a value at the given index if the generation is equal to the
332    /// generation associated with the existing element.
333    ///
334    /// Returns the previous generation and the value for the element if successful.
335    ///
336    /// # Errors
337    ///
338    /// Errors are returned if:
339    ///
340    /// * the index is out of bounds
341    /// * the generation of the generational index is less than the generation associated with the element
342    ///
343    /// # Panics
344    ///
345    /// * if the generation is greater than the current generation associated
346    /// with the element. To increase the generation, a call to
347    /// [`set_next_gen`][UnmanagedGenVec::set_next_gen] must be called first.
348    #[inline]
349    pub fn set(&mut self, gen_index: GenIndex, value: T) -> Result<(G, T), Error>
350    where
351        GenIndex: Into<(I, G)>,
352        G: PartialOrd,
353        I: Into<usize>,
354    {
355        let gen_index = gen_index.into();
356        self.internal_set(gen_index.0.into(), gen_index.1, value)
357    }
358
359    /// Sets or pushes the element at the index if the generation is equal to
360    /// the existing generation associated with the element.
361    ///
362    /// Returns the previous generation and the value for the element if
363    /// replacing an existing value.
364    ///
365    /// This method is a convenience method for the newest allocated
366    /// generational index. Either the newest allocated generationl index is
367    /// for an existing index or it is for the immediate next index if a
368    /// value were to be pushed to the `Vec`.
369    ///
370    /// # Errors
371    ///
372    /// Errors are returned if:
373    ///
374    /// * the index is out of bounds
375    /// * the generation of the generational index is less than the generation associated with the element
376    ///
377    /// # Panics
378    ///
379    /// * if the index is greater than the length of the inner vector
380    /// * if the generation is greater than the current generation associated
381    /// with the element. To increase the generation, a call to
382    /// [`set_next_gen`][UnmanagedGenVec::set_next_gen] must be called first.
383    pub fn set_or_push(&mut self, gen_index: GenIndex, value: T) -> Result<Option<(G, T)>, Error>
384    where
385        GenIndex: Into<(I, G)>,
386        G: PartialOrd,
387        I: Into<usize>,
388    {
389        let (index, generation) = gen_index.into();
390        let index = index.into();
391
392        match index.cmp(&self.len()) {
393            Ordering::Less => self.internal_set(index, generation, value).map(Some),
394            Ordering::Equal => {
395                debug_assert_eq!(index, self.len());
396                self.push_with_gen(generation, value);
397                Ok(None)
398            }
399            Ordering::Greater => Err(Error::index_out_of_bounds()),
400        }
401    }
402
403    /// Sets the next generation for an index. The `gen_index` parameter is
404    /// composed of the index and the next generation of the current generation
405    /// associated with the element.
406    ///
407    /// Returns the previous generation if successful.
408    ///
409    /// # Errors
410    ///
411    /// Errors are returned if:
412    ///
413    /// * the index is out of bounds
414    /// * the generation is less than or equal to the existing generation associated with
415    /// the element
416    ///
417    /// # Panics
418    ///
419    /// Panics if the generation is not the next generation after the existing
420    /// generation associated with the element.
421    pub fn set_next_gen(&mut self, gen_index: GenIndex) -> Result<G, Error>
422    where
423        GenIndex: Into<(I, G)>,
424        G: PartialOrd + Incrementable,
425        I: Into<usize>,
426    {
427        let (index, generation) = gen_index.into();
428        let elem = self
429            .inner
430            .get_mut(index.into())
431            .ok_or_else(Error::index_out_of_bounds)?;
432        if elem.0 < generation {
433            assert!(
434                elem.0.next().as_ref() == Some(&generation),
435                "generation is not the next generation of the current element"
436            );
437            let prev_value = core::mem::replace(&mut elem.0, generation);
438            Ok(prev_value)
439        } else if elem.0 == generation {
440            Err(Error::already_equal_generation())
441        } else {
442            Err(Error::less_than_existing_generation())
443        }
444    }
445
446    /// Sets the generation for an index.
447    ///
448    /// Any existing generational indexes equal to or greater than the given
449    /// generation could be considered valid again.
450    ///
451    /// Normally, this method should never be called in a program. In
452    /// exceptional conditions (such as when an index has exhausted all
453    /// generations and all generational indexes referencing the index have been
454    /// removed from the program), the method could be called.
455    ///
456    /// # Errors
457    ///
458    /// Errors are returned if:
459    ///
460    /// * the index is out of bounds
461    pub fn set_gen(&mut self, gen_index: GenIndex) -> Result<G, Error>
462    where
463        GenIndex: Into<(I, G)>,
464        I: Into<usize>,
465    {
466        let (index, generation) = gen_index.into();
467        let elem = self
468            .inner
469            .get_mut(index.into())
470            .ok_or_else(Error::index_out_of_bounds)?;
471        let prev_value = core::mem::replace(&mut elem.0, generation);
472        Ok(prev_value)
473    }
474}
475
476impl<T, G, I, GenIndex> core::ops::Index<GenIndex> for UnmanagedGenVec<T, G, I, GenIndex>
477where
478    I: Into<usize>,
479    GenIndex: Into<(I, G)>,
480    G: PartialEq,
481{
482    type Output = T;
483
484    fn index(&self, gen_index: GenIndex) -> &Self::Output {
485        let gen_index = gen_index.into();
486        let idx = gen_index.0.into();
487        let (cur_gen, elem) = &self.inner[idx];
488        let expected_gen = gen_index.1;
489        if expected_gen == *cur_gen {
490            elem
491        } else {
492            panic!("generation is not equal");
493        }
494    }
495}
496
497impl<T, G, I, GenIndex> core::ops::IndexMut<GenIndex> for UnmanagedGenVec<T, G, I, GenIndex>
498where
499    I: Into<usize>,
500    GenIndex: Into<(I, G)>,
501    G: PartialEq,
502{
503    fn index_mut(&mut self, gen_index: GenIndex) -> &mut Self::Output {
504        let gen_index = gen_index.into();
505        let idx = gen_index.0.into();
506        let (cur_gen, elem) = &mut self.inner[idx];
507        let expected_gen = gen_index.1;
508        if expected_gen == *cur_gen {
509            elem
510        } else {
511            panic!("generation is not equal");
512        }
513    }
514}
515
516#[cfg(test)]
517mod tests {
518    use super::*;
519
520    #[derive(Debug, PartialEq)]
521    struct Value<T>(T);
522
523    impl<T> Value<T> {
524        fn set(&mut self, value: T) {
525            self.0 = value;
526        }
527    }
528
529    #[test]
530    fn test_contains_index_out_of_bounds() {
531        let gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
532        assert!(!gen_vec.contains_index((0, 0)));
533    }
534
535    #[test]
536    fn test_contains_index_generation_less_than_existing() {
537        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
538        gen_vec.push_with_gen(1, Value(0));
539        assert!(!gen_vec.contains_index((0, 0)));
540    }
541
542    #[test]
543    fn test_contains_index_generation_greater_than_existing() {
544        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
545        gen_vec.push_with_gen(1, Value(0));
546        assert!(!gen_vec.contains_index((2, 0)));
547    }
548
549    #[test]
550    fn test_get_index_out_of_bounds() {
551        let gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
552        let err = gen_vec.get((0, 0)).unwrap_err();
553        assert!(err.is_index_out_of_bounds());
554    }
555
556    #[test]
557    fn test_get_generation_less_than_existing() {
558        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
559        gen_vec.push_with_gen(1, Value(0));
560
561        let err = gen_vec.get((0, 0)).unwrap_err();
562        assert!(err.is_not_equal_generation_error());
563    }
564
565    #[test]
566    fn test_get_generation_greater_than_existing() {
567        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
568        gen_vec.push_with_gen(1, Value(0));
569
570        let err = gen_vec.get((0, 2)).unwrap_err();
571        assert!(err.is_not_equal_generation_error());
572    }
573
574    #[test]
575    fn test_get_mut_index_out_of_bounds() {
576        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
577        let err = gen_vec.get_mut((0, 0)).unwrap_err();
578        assert!(err.is_index_out_of_bounds());
579    }
580
581    #[test]
582    fn test_get_mut_generation_less_than_existing() {
583        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
584        gen_vec.push_with_gen(1, Value(0));
585
586        let err = gen_vec.get_mut((0, 0)).unwrap_err();
587        assert!(err.is_not_equal_generation_error());
588    }
589
590    #[test]
591    fn test_get_mut_generation_greater_than_existing() {
592        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
593        gen_vec.push_with_gen(1, Value(0));
594
595        let err = gen_vec.get_mut((0, 2)).unwrap_err();
596        assert!(err.is_not_equal_generation_error());
597    }
598
599    #[test]
600    fn test_get_gen_index_out_of_bounds() {
601        let gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
602
603        assert_eq!(gen_vec.get_gen(0), None);
604    }
605
606    #[test]
607    fn test_set_index_out_of_bounds() {
608        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
609        let err = gen_vec.set((0, 0), Value(1)).unwrap_err();
610        assert!(err.is_index_out_of_bounds());
611    }
612
613    #[test]
614    fn test_set_generation_less_than_existing() {
615        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
616        gen_vec.push_with_gen(1, Value(0));
617        let err = gen_vec.set((0, 0), Value(1)).unwrap_err();
618        assert!(err.is_generation_less_than_existing());
619    }
620
621    #[test]
622    #[should_panic(expected = "generation is greater than generation associated with element")]
623    fn test_set_generation_greater_than_existing() {
624        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
625        gen_vec.push_with_gen(0, Value(0));
626        gen_vec.set((0, 1), Value(1)).unwrap();
627    }
628
629    #[test]
630    fn test_set_or_push_index_out_of_bounds() {
631        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
632        let err = gen_vec.set_or_push((1, 0), Value(1)).unwrap_err();
633        assert!(err.is_index_out_of_bounds());
634    }
635
636    #[test]
637    fn test_set_or_push_generation_less_than_existing() {
638        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
639        gen_vec.push_with_gen(1, Value(0));
640        let err = gen_vec.set((0, 0), Value(1)).unwrap_err();
641        assert!(err.is_generation_less_than_existing());
642    }
643
644    #[test]
645    #[should_panic(expected = "generation is greater than generation associated with element")]
646    fn test_set_or_push_generation_greater_than_existing() {
647        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
648        gen_vec.push_with_gen(0, Value(0));
649        gen_vec.set((0, 1), Value(1)).unwrap();
650    }
651
652    #[test]
653    fn test_set_next_gen_index_out_of_bounds() {
654        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
655        let err = gen_vec.set_next_gen((0, 1)).unwrap_err();
656        assert!(err.is_index_out_of_bounds());
657    }
658
659    #[test]
660    fn test_set_next_gen_generation_already_equal() {
661        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
662        gen_vec.push_with_gen(1, Value(0));
663        let err = gen_vec.set_next_gen((0, 1)).unwrap_err();
664        assert!(err.is_already_equal_generation_error());
665    }
666
667    #[test]
668    fn test_set_next_gen_generation_less_than_existing() {
669        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
670        gen_vec.push_with_gen(2, Value(0));
671        let err = gen_vec.set_next_gen((0, 1)).unwrap_err();
672        assert!(err.is_generation_less_than_existing());
673    }
674
675    #[test]
676    #[should_panic(expected = "generation is not the next generation of the current element")]
677    fn test_set_next_gen_generation_greater_than_more_than_one_existing() {
678        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
679        gen_vec.push_with_gen(1, Value(0));
680        let _ = gen_vec.set_next_gen((0, 3));
681    }
682
683    #[test]
684    #[should_panic(expected = "index out of bounds")]
685    fn test_index_out_of_bounds_index() {
686        let gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
687        let _ = gen_vec[(0, 0)];
688    }
689
690    #[test]
691    #[should_panic(expected = "generation is not equal")]
692    fn test_index_generation_less_than_existing() {
693        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
694        gen_vec.push_with_gen(1, Value(0));
695        let _ = &gen_vec[(0, 0)];
696    }
697
698    #[test]
699    #[should_panic(expected = "generation is not equal")]
700    fn test_index_generation_greater_than_existing() {
701        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
702        gen_vec.push_with_gen(0, Value(0));
703        let _ = &gen_vec[(0, 1)];
704    }
705
706    #[test]
707    #[should_panic(expected = "index out of bounds")]
708    fn test_index_mut_out_of_bounds_index() {
709        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
710        let _ = &mut gen_vec[(0, 0)];
711    }
712
713    #[test]
714    #[should_panic(expected = "generation is not equal")]
715    fn test_index_mut_generation_less_than_existing() {
716        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
717        gen_vec.push_with_gen(1, Value(0));
718        let _ = &mut gen_vec[(0, 0)];
719    }
720
721    #[test]
722    #[should_panic(expected = "generation is not equal")]
723    fn test_index_mut_generation_greater_than_existing() {
724        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
725        gen_vec.push_with_gen(0, Value(0));
726        let _ = &mut gen_vec[(0, 1)];
727    }
728
729    #[test]
730    fn test_index_mut() {
731        let mut gen_vec = UnmanagedGenVec::<Value<u32>, u8>::default();
732
733        let index = gen_vec.len();
734        assert_eq!(index, 0);
735        let generation = 0;
736        gen_vec.push_with_gen(generation, Value(0));
737        assert_eq!(gen_vec[(index, generation)], Value(0));
738
739        let value = &mut gen_vec[(index, generation)];
740        value.set(9);
741        assert_eq!(gen_vec[(index, generation)], Value(9));
742    }
743}