osiris/types/
array.rs

1//! This module implements static and dynamic arrays for in-kernel use.
2
3use crate::{error::Result, types::bitset::BitAlloc};
4
5use super::{
6    boxed::Box,
7    traits::{Get, GetMut, ToIndex},
8};
9
10use core::mem::ManuallyDrop;
11use core::ops::{Index, IndexMut};
12use core::{borrow::Borrow, mem::MaybeUninit};
13
14/// This is a fixed-size map that can store up to N consecutive elements.
15#[proc_macros::fmt]
16pub struct IndexMap<K: ?Sized + ToIndex, V, const N: usize> {
17    data: [Option<V>; N],
18    phantom: core::marker::PhantomData<K>,
19}
20
21#[allow(dead_code)]
22impl<K: ?Sized + ToIndex, V, const N: usize> IndexMap<K, V, N> {
23    /// Create a new IndexMap.
24    ///
25    /// Returns a new IndexMap.
26    pub const fn new() -> Self {
27        Self {
28            data: [const { None }; N],
29            phantom: core::marker::PhantomData,
30        }
31    }
32
33    /// Insert a value at the given index.
34    ///
35    /// `index` - The index to insert the value at.
36    /// `value` - The value to insert.
37    ///
38    /// Returns `Ok(())` if the index was in-bounds, otherwise `Err(KernelError::OutOfMemory)`.
39    pub fn insert(&mut self, idx: &K, value: V) -> Result<()> {
40        let idx = K::to_index(Some(idx));
41
42        if idx < N {
43            self.data[idx] = Some(value);
44            Ok(())
45        } else {
46            Err(kerr!(OutOfMemory))
47        }
48    }
49
50    /// Remove the value at the given index.
51    ///
52    /// `index` - The index to remove the value from.
53    ///
54    /// Returns the value if it was removed, otherwise `None`.
55    pub fn remove(&mut self, idx: &K) -> Option<V> {
56        let idx = K::to_index(Some(idx));
57
58        if idx < N { self.data[idx].take() } else { None }
59    }
60
61    pub fn raw_insert(&mut self, idx: usize, value: V) -> Result<()> {
62        if idx < N {
63            self.data[idx] = Some(value);
64            Ok(())
65        } else {
66            Err(kerr!(OutOfMemory))
67        }
68    }
69
70    pub fn raw_remove(&mut self, idx: usize) -> Option<V> {
71        if idx < N { self.data[idx].take() } else { None }
72    }
73
74    pub fn raw_at(&self, idx: usize) -> Option<&V> {
75        if idx < N {
76            self.data[idx].as_ref()
77        } else {
78            None
79        }
80    }
81
82    pub fn raw_at_mut(&mut self, idx: usize) -> Option<&mut V> {
83        if idx < N {
84            self.data[idx].as_mut()
85        } else {
86            None
87        }
88    }
89}
90
91impl<K: Copy + ToIndex, V, const N: usize> Index<K> for IndexMap<K, V, N> {
92    type Output = V;
93
94    fn index(&self, index: K) -> &Self::Output {
95        self.get::<K>(index).unwrap()
96    }
97}
98
99impl<K: Copy + ToIndex, V, const N: usize> IndexMut<K> for IndexMap<K, V, N> {
100    fn index_mut(&mut self, index: K) -> &mut Self::Output {
101        self.get_mut::<K>(index).unwrap()
102    }
103}
104
105impl<K: ?Sized + ToIndex, V, const N: usize> Get<K> for IndexMap<K, V, N> {
106    type Output = V;
107
108    fn get<Q: Borrow<K>>(&self, index: Q) -> Option<&Self::Output> {
109        let idx = K::to_index(Some(index.borrow()));
110        if idx < N {
111            self.data[idx].as_ref()
112        } else {
113            None
114        }
115    }
116}
117
118impl<K: ?Sized + ToIndex, V, const N: usize> GetMut<K> for IndexMap<K, V, N> {
119    fn get_mut<Q: Borrow<K>>(&mut self, index: Q) -> Option<&mut Self::Output> {
120        let idx = K::to_index(Some(index.borrow()));
121        if idx < N {
122            self.data[idx].as_mut()
123        } else {
124            None
125        }
126    }
127
128    fn get2_mut<Q: Borrow<K>>(
129        &mut self,
130        index1: Q,
131        index2: Q,
132    ) -> (Option<&mut Self::Output>, Option<&mut Self::Output>) {
133        let idx1 = K::to_index(Some(index1.borrow()));
134        let idx2 = K::to_index(Some(index2.borrow()));
135
136        if idx1 == idx2 {
137            debug_assert!(false, "get2_mut called with identical indices");
138            return (None, None);
139        }
140
141        let (left, right) = self.data.split_at_mut(idx1.max(idx2));
142
143        if idx1 < idx2 {
144            let elem1 = left[idx1].as_mut();
145            let elem2 = right[0].as_mut();
146            (elem1, elem2)
147        } else {
148            let elem1 = right[0].as_mut();
149            let elem2 = left[idx2].as_mut();
150            (elem1, elem2)
151        }
152    }
153
154    fn get3_mut<Q: Borrow<K>>(
155        &mut self,
156        index1: Q,
157        index2: Q,
158        index3: Q,
159    ) -> (
160        Option<&mut Self::Output>,
161        Option<&mut Self::Output>,
162        Option<&mut Self::Output>,
163    ) {
164        let idx1 = K::to_index(Some(index1.borrow()));
165        let idx2 = K::to_index(Some(index2.borrow()));
166        let idx3 = K::to_index(Some(index3.borrow()));
167
168        if idx1 == idx2 || idx1 == idx3 || idx2 == idx3 {
169            debug_assert!(false, "get3_mut called with identical indices");
170            return (None, None, None);
171        }
172
173        let ptr1 = &mut self.data[idx1] as *mut Option<V>;
174        let ptr2 = &mut self.data[idx2] as *mut Option<V>;
175        let ptr3 = &mut self.data[idx3] as *mut Option<V>;
176
177        // Safety: the elements at index1, index2 and index3 are nowhere else borrowed mutably by function contract.
178        // And they are disjoint because of the check above.
179        unsafe { ((*ptr1).as_mut(), (*ptr2).as_mut(), (*ptr3).as_mut()) }
180    }
181}
182
183/// This is a vector that can store up to N elements inline and will allocate on the heap if more are needed.
184#[proc_macros::fmt]
185pub struct Vec<T, const N: usize> {
186    len: usize,
187    data: [MaybeUninit<T>; N],
188    extra: Box<[MaybeUninit<T>]>,
189}
190
191#[allow(dead_code)]
192impl<T: Clone + Copy, const N: usize> Vec<T, N> {
193    /// Create a new Vec.
194    ///
195    /// Returns a new Vec.
196    pub const fn new() -> Self {
197        Self {
198            len: 0,
199            data: [const { MaybeUninit::uninit() }; N],
200            extra: Box::new_slice_empty(),
201        }
202    }
203
204    pub const fn from_array(arr: [T; N]) -> Self {
205        let arr = ManuallyDrop::new(arr);
206        let mut data = [const { MaybeUninit::uninit() }; N];
207
208        let src: *const [T; N] = &arr as *const ManuallyDrop<[T; N]> as *const [T; N];
209        let dst: *mut [MaybeUninit<T>; N] = &mut data;
210
211        let mut i = 0;
212        while i < N {
213            unsafe {
214                let value = core::ptr::read((src as *const T).add(i));
215                (dst as *mut MaybeUninit<T>)
216                    .add(i)
217                    .write(MaybeUninit::new(value));
218            }
219            i += 1;
220        }
221
222        Self {
223            len: N,
224            data,
225            extra: Box::new_slice_empty(),
226        }
227    }
228
229    /// Reserve additional space in the Vec.
230    ///
231    /// `additional` - The additional space to reserve.
232    ///
233    /// Returns `Ok(())` if the space was reserved, otherwise `Err(KernelError::OutOfMemory)`.
234    pub fn reserve(&mut self, additional: usize) -> Result<()> {
235        let len_extra = self.extra.len();
236
237        // Check if we have enough space in the inline storage.
238        if self.len + additional <= N + len_extra {
239            return Ok(());
240        }
241
242        // If we don't have enough space, we need to grow the extra storage.
243        let grow = self.len + additional - N;
244        let mut new_extra = Box::new_slice_uninit(grow)?;
245
246        // Check that the new extra storage has the requested length.
247        bug_on!(new_extra.len() != grow);
248
249        // Copy the old extra storage into the new one.
250        new_extra[..len_extra].copy_from_slice(&self.extra);
251
252        // Replace the old extra storage with the new one. The old one will be dropped.
253        self.extra = new_extra;
254        Ok(())
255    }
256
257    /// Reserve a fixed amount of space in the Vec. Does nothing if enough space is present already.
258    ///
259    /// `total_capacity` - The total space to be reserved.
260    ///
261    /// Returns `Ok(())` if the space was reserved, otherwise `Err(KernelError::OutOfMemory)`.
262    pub fn reserve_total_capacity(&mut self, total_capacity: usize) -> Result<()> {
263        // Check if we already have enough space
264        if self.capacity() >= total_capacity {
265            return Ok(());
266        }
267
268        // If we don't have enough space, we need to grow the extra storage.
269        let new_out_of_line_cap = total_capacity - N;
270        let mut new_extra = Box::new_slice_uninit(new_out_of_line_cap)?;
271
272        // Check that the new extra storage has the requested length.
273        bug_on!(new_extra.len() != new_out_of_line_cap);
274
275        let curr_out_of_line_size = self.extra.len();
276        // Copy the old extra storage into the new one.
277        new_extra[..curr_out_of_line_size].copy_from_slice(&self.extra);
278
279        // Replace the old extra storage with the new one. The old one will be dropped.
280        self.extra = new_extra;
281        Ok(())
282    }
283
284    /// Create a new Vec with the given length and value.
285    ///
286    /// `length` - The length of the Vec.
287    /// `value` - The value to initialize the elements in the Vec with.
288    ///
289    /// Returns the new Vec or `Err(KernelError::OutOfMemory)` if the allocation failed.
290    pub fn new_init(length: usize, value: T) -> Result<Self> {
291        let mut vec = Self::new();
292
293        // Check if we can fit all elements in the inline storage.
294        if length <= N {
295            // Initialize all elements in the inline storage.
296            for i in 0..length {
297                vec.data[i].write(value);
298            }
299        } else {
300            // Initialize all elements in the inline storage.
301            vec.data.fill(MaybeUninit::new(value));
302
303            // Check if we need to allocate extra storage.
304            if length - N > 0 {
305                // Allocate extra storage for the remaining elements.
306                let mut extra = Box::new_slice_uninit(length - N)?;
307
308                // Initialize all the required elements in the extra storage.
309                for i in N..length {
310                    extra[i - N].write(value);
311                }
312
313                // Set the extra storage in the Vec.
314                vec.extra = extra;
315            }
316        }
317
318        Ok(vec)
319    }
320
321    /// Push a value onto the Vec.
322    ///
323    /// `value` - The value to push.
324    ///
325    /// Returns `Ok(())` if the value was pushed, otherwise `Err(KernelError::OutOfMemory)`.
326    pub fn push(&mut self, value: T) -> Result<()> {
327        // Check if we have enough space in the inline storage.
328        if self.len < N {
329            // Push the value into the inline storage.
330            self.data[self.len].write(value);
331            self.len += 1;
332            Ok(())
333        } else {
334            let len_extra = self.extra.len();
335
336            // Check if we have enough space in the extra storage.
337            if self.len < N + len_extra {
338                // Push the value into the extra storage.
339                self.extra[self.len - N].write(value);
340                self.len += 1;
341                Ok(())
342            } else {
343                // We need to grow the extra storage.
344                let grow = (len_extra + 1) * 2;
345                let mut new_extra = Box::new_slice_uninit(grow)?;
346
347                bug_on!(new_extra.len() != grow);
348
349                // Copy the old extra storage into the new one.
350                new_extra[..len_extra].copy_from_slice(&self.extra);
351
352                // Replace the old extra storage with the new one. The old one will be dropped.
353                self.extra = new_extra;
354                self.extra[len_extra].write(value);
355                self.len += 1;
356                Ok(())
357            }
358        }
359    }
360
361    /// Pop a value from the Vec.
362    ///
363    /// Returns the value if it was popped, otherwise `None`.
364    pub fn pop(&mut self) -> Option<T> {
365        if self.len == 0 {
366            return None;
367        }
368        self.remove(self.len - 1)
369    }
370
371    /// Remove the value at the given index.
372    ///
373    /// `index` - The index to remove the value from.
374    ///
375    /// Returns the value if it was removed, otherwise `None`.
376    pub fn remove(&mut self, index: usize) -> Option<T> {
377        // Check if the index is in-bounds.
378        if index >= self.len {
379            return None;
380        }
381
382        // Get the value at the given index.
383        let value = self.at(index).cloned();
384
385        // Check if we need to move inline storage elements.
386        if index < N {
387            // Move the elements in the inline storage.
388            let end = core::cmp::min(self.len, N);
389
390            // Safety: index is less than N and min too.
391            self.data.copy_within(index + 1..end, index);
392
393            // Check if we need to move the first extra storage element into the inline storage.
394            if let Some(value) = self.at(N) {
395                self.data[end - 1].write(*value);
396            }
397
398            // Move the elements in the extra storage.
399            if self.len() > N {
400                self.extra.copy_within(1..self.len - N, 0);
401            }
402        } else {
403            // We only need to move the elements in the extra storage.
404
405            let index = index - N;
406            let end = self.len - N;
407
408            // Safety: index is less than N and min too.
409            self.extra.copy_within(index + 1..end, index);
410        }
411
412        self.len -= 1;
413        value
414    }
415
416    /// Get the length of the Vec.
417    ///
418    /// Returns the length of the Vec.
419    pub fn len(&self) -> usize {
420        self.len
421    }
422
423    /// Get the value at the given index.
424    ///
425    /// `index` - The index to get the value from.
426    ///
427    /// Returns `Some(&T)` if the index is in-bounds, otherwise `None`.
428    pub fn at(&self, index: usize) -> Option<&T> {
429        // Check if the index is in-bounds.
430        if index >= self.len {
431            return None;
432        }
433
434        if index < N {
435            // Safety: the elements until self.len are initialized.
436            unsafe { Some(self.data[index].assume_init_ref()) }
437        } else {
438            let index = index - N;
439            // Safety: the elements until self.len - N are initialized.
440            unsafe { Some(self.extra[index].assume_init_ref()) }
441        }
442    }
443
444    /// Get a mutable reference to the value at the given index.
445    ///
446    /// `index` - The index to get the value from.
447    ///
448    /// Returns `Some(&mut T)` if the index is in-bounds, otherwise `None`.
449    pub fn at_mut(&mut self, index: usize) -> Option<&mut T> {
450        // Check if the index is in-bounds.
451        if index >= self.len {
452            return None;
453        }
454
455        if index < N {
456            // Safety: the elements until self.len are initialized.
457            unsafe { Some(self.data[index].assume_init_mut()) }
458        } else {
459            let index = index - N;
460            // Safety: the elements until self.len - N are initialized.
461            unsafe { Some(self.extra[index].assume_init_mut()) }
462        }
463    }
464
465    fn at_mut_unchecked(&mut self, index: usize) -> *mut T {
466        if index < N {
467            // Safety: the elements until self.len are initialized.
468            // The element at index is nowhere else borrowed mutably by function contract.
469            self.data[index].as_mut_ptr()
470        } else {
471            let index = index - N;
472            // Safety: the elements until self.len - N are initialized.
473            // The element at index is nowhere else borrowed mutably by function contract.
474            self.extra[index].as_mut_ptr()
475        }
476    }
477
478    /// Get disjoint mutable references to the values at the given indices.
479    ///
480    /// `index1` - The first index.
481    /// `index2` - The second index.
482    ///
483    /// Returns `Some(&mut T, &mut T)` if the indices are in-bounds and disjoint, otherwise `None`.
484    pub fn at2_mut(&mut self, index1: usize, index2: usize) -> (Option<&mut T>, Option<&mut T>) {
485        if index1 == index2 {
486            debug_assert!(false, "at2_mut called with identical indices");
487            return (None, None);
488        }
489
490        let ptr1 = self.at_mut_unchecked(index1);
491        let ptr2 = self.at_mut_unchecked(index2);
492
493        // Safety: the elements at index1 and index2 are nowhere else borrowed mutably by function contract.
494        // And they are disjoint because of the check above.
495        unsafe { (Some(&mut *ptr1), Some(&mut *ptr2)) }
496    }
497
498    /// Get disjoint mutable references to the values at the given indices.
499    ///
500    /// `index1` - The first index.
501    /// `index2` - The second index.
502    /// `index3` - The third index.
503    ///
504    /// Returns `Some(&mut T, &mut T, &mut T)` if the indices are in-bounds and disjoint, otherwise `None`.
505    pub fn at3_mut(
506        &mut self,
507        index1: usize,
508        index2: usize,
509        index3: usize,
510    ) -> (Option<&mut T>, Option<&mut T>, Option<&mut T>) {
511        if index1 == index2 || index1 == index3 || index2 == index3 {
512            debug_assert!(false, "at3_mut called with identical indices");
513            return (None, None, None);
514        }
515
516        let ptr1 = self.at_mut_unchecked(index1);
517        let ptr2 = self.at_mut_unchecked(index2);
518        let ptr3 = self.at_mut_unchecked(index3);
519
520        // Safety: the elements at index1, index2 and index3 are nowhere else borrowed mutably by function contract.
521        // And they are disjoint because of the check above.
522        unsafe { (Some(&mut *ptr1), Some(&mut *ptr2), Some(&mut *ptr3)) }
523    }
524
525    /// Swap the values at the given indices.
526    ///
527    /// `a` - The first index.
528    /// `b` - The second index.
529    pub fn swap(&mut self, a: usize, b: usize) {
530        // Check if the indices are in-bounds.
531        if a >= self.len || b >= self.len {
532            return;
533        }
534
535        if a < N && b < N {
536            // Both indices are in the inline storage.
537            self.data.swap(a, b);
538        } else if a >= N && b >= N {
539            // Both indices are in the extra storage.
540            self.extra.swap(a - N, b - N);
541        } else if a >= N {
542            // The first index is in the extra storage.
543            core::mem::swap(&mut self.extra[a - N], &mut self.data[b]);
544        } else {
545            // The second index is in the extra storage.
546            core::mem::swap(&mut self.data[a], &mut self.extra[b - N]);
547        }
548    }
549
550    /// Check if the Vec is empty.
551    ///
552    /// Returns `true` if the Vec is empty, otherwise `false`.
553    pub fn is_empty(&self) -> bool {
554        self.len == 0
555    }
556
557    /// Get total amount of space in Vec (in- and out-of-line)
558    ///
559    /// Returns total amount of  reserved space in the vec
560    pub fn capacity(&self) -> usize {
561        N + self.extra.len()
562    }
563}
564
565impl<T, const N: usize> Drop for Vec<T, N> {
566    fn drop(&mut self) {
567        let min = core::cmp::min(self.len, N);
568
569        // Drop all elements in the inline storage.
570        for elem in &mut self.data[0..min] {
571            // Safety: the elements until min are initialized.
572            unsafe {
573                elem.assume_init_drop();
574            }
575        }
576
577        // Drop all elements in the extra storage.
578        for elem in &mut (*self.extra)[0..self.len - min] {
579            // Safety: the elements until self.len - N are initialized.
580            unsafe {
581                elem.assume_init_drop();
582            }
583        }
584    }
585}
586
587impl<T, const N: usize> Clone for Vec<T, N>
588where
589    T: Clone + Copy,
590{
591    fn clone(&self) -> Self {
592        let mut new_vec = Self::new();
593        let min = core::cmp::min(self.len, N);
594
595        // Clone the elements in the inline storage.
596        for i in 0..min {
597            // Safety: the elements until self.len are initialized.
598            let value = unsafe { self.data[i].assume_init_ref() };
599            new_vec.data[i].write(*value);
600        }
601
602        // Clone the elements in the extra storage.
603        for i in 0..self.len - min {
604            // Safety: the elements until self.len - N are initialized.
605            let value = unsafe { self.extra[i].assume_init_ref() };
606            new_vec.extra[i].write(*value);
607        }
608
609        new_vec.len = self.len;
610        new_vec
611    }
612}
613
614impl<T: Clone + Copy, const N: usize> Index<usize> for Vec<T, N> {
615    type Output = T;
616
617    fn index(&self, index: usize) -> &Self::Output {
618        self.at(index).unwrap()
619    }
620}
621
622impl<T: Clone + Copy, const N: usize> IndexMut<usize> for Vec<T, N> {
623    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
624        self.at_mut(index).unwrap()
625    }
626}
627
628impl<T: Clone + Copy, const N: usize> Get<usize> for Vec<T, N> {
629    type Output = T;
630
631    fn get<Q: Borrow<usize>>(&self, index: Q) -> Option<&Self::Output> {
632        self.at(*index.borrow())
633    }
634}
635
636impl<T: Clone + Copy, const N: usize> GetMut<usize> for Vec<T, N> {
637    fn get_mut<Q: Borrow<usize>>(&mut self, index: Q) -> Option<&mut Self::Output> {
638        self.at_mut(*index.borrow())
639    }
640
641    fn get2_mut<Q: Borrow<usize>>(
642        &mut self,
643        index1: Q,
644        index2: Q,
645    ) -> (Option<&mut Self::Output>, Option<&mut Self::Output>) {
646        self.at2_mut(*index1.borrow(), *index2.borrow())
647    }
648
649    fn get3_mut<Q: Borrow<usize>>(
650        &mut self,
651        index1: Q,
652        index2: Q,
653        index3: Q,
654    ) -> (
655        Option<&mut Self::Output>,
656        Option<&mut Self::Output>,
657        Option<&mut Self::Output>,
658    ) {
659        self.at3_mut(*index1.borrow(), *index2.borrow(), *index3.borrow())
660    }
661}
662
663/// This is an IndexMap that additionally tracks which indices are occupied through a bitset.
664pub struct BitReclaimMap<K: ?Sized + ToIndex, V, const N: usize> {
665    map: IndexMap<K, V, N>,
666    free: BitAlloc<N>,
667}
668
669impl<K: ?Sized + ToIndex, V, const N: usize> BitReclaimMap<K, V, N> {
670    pub const fn new() -> Self {
671        Self {
672            map: IndexMap::new(),
673            free: BitAlloc::from_array([!0usize; N]),
674        }
675    }
676
677    #[allow(dead_code)]
678    pub fn insert(&mut self, value: V) -> Result<usize> {
679        let idx = self.free.alloc(1).ok_or(kerr!(OutOfMemory))?;
680        self.map.raw_insert(idx, value)?;
681        Ok(idx)
682    }
683
684    pub fn remove(&mut self, idx: &K) -> Option<V> {
685        self.map.remove(idx).inspect(|_| {
686            self.free.free(K::to_index(Some(idx)), 1);
687        })
688    }
689}
690
691impl<K: Copy + ToIndex, V, const N: usize> BitReclaimMap<K, V, N> {
692    pub fn insert_with(&mut self, f: impl FnOnce(usize) -> Result<(K, V)>) -> Result<K> {
693        let idx = self.free.alloc(1).ok_or(kerr!(OutOfMemory))?;
694        let (key, value) = f(idx)?;
695        self.map.raw_insert(idx, value)?;
696        Ok(key)
697    }
698}
699
700impl<K: Copy + ToIndex, V, const N: usize> Index<K> for BitReclaimMap<K, V, N> {
701    type Output = V;
702
703    fn index(&self, index: K) -> &Self::Output {
704        self.get::<K>(index).unwrap()
705    }
706}
707
708impl<K: Copy + ToIndex, V, const N: usize> IndexMut<K> for BitReclaimMap<K, V, N> {
709    fn index_mut(&mut self, index: K) -> &mut Self::Output {
710        self.get_mut::<K>(index).unwrap()
711    }
712}
713
714impl<K: ?Sized + ToIndex, V, const N: usize> Get<K> for BitReclaimMap<K, V, N> {
715    type Output = V;
716
717    fn get<Q: Borrow<K>>(&self, index: Q) -> Option<&Self::Output> {
718        self.map.get(index)
719    }
720}
721
722impl<K: ?Sized + ToIndex, V, const N: usize> GetMut<K> for BitReclaimMap<K, V, N> {
723    fn get_mut<Q: Borrow<K>>(&mut self, index: Q) -> Option<&mut Self::Output> {
724        self.map.get_mut(index)
725    }
726
727    fn get2_mut<Q: Borrow<K>>(
728        &mut self,
729        index1: Q,
730        index2: Q,
731    ) -> (Option<&mut Self::Output>, Option<&mut Self::Output>) {
732        self.map.get2_mut(index1, index2)
733    }
734
735    fn get3_mut<Q: Borrow<K>>(
736        &mut self,
737        index1: Q,
738        index2: Q,
739        index3: Q,
740    ) -> (
741        Option<&mut Self::Output>,
742        Option<&mut Self::Output>,
743        Option<&mut Self::Output>,
744    ) {
745        self.map.get3_mut(index1, index2, index3)
746    }
747}
748
749#[cfg(test)]
750mod tests {
751    use super::Vec;
752
753    #[test]
754    fn no_length_underflow() {
755        let vec = Vec::<usize, 8>::new();
756        assert!(vec.len() == 0);
757        assert_eq!(vec.at(0), None);
758    }
759
760    #[test]
761    fn reserve_works() {
762        let mut vec = Vec::<usize, 8>::new();
763        for i in 0..7usize {
764            vec.push(i).unwrap();
765        }
766        assert_eq!(vec.len(), 7);
767
768        let _ = vec.reserve(2);
769    }
770
771    #[test]
772    fn drop_underflow() {
773        let mut vec = Vec::<usize, 8>::new();
774        for i in 0..7usize {
775            vec.push(i).unwrap();
776        }
777        drop(vec);
778    }
779}