rate_common/memory/
array.rs

1//! `Array` is a non-growable
2//! [`std::vec::Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html)` with
3//! strongly-typed indexing.
4
5use crate::memory::{assert_in_bounds, HeapSpace, Offset, Vector};
6use std::{
7    marker::PhantomData,
8    ops::{Deref, DerefMut, Index, IndexMut},
9};
10
11/// A contiguous non-growable array type with strongly-typed indexing.
12///
13/// The first template argument specifies the type that can be used for
14/// indexing the array. The second template argument specifies the type of
15/// the elements in the array.
16///
17/// An `Array` can be used as a fixed size map or set data structure.
18/// The maximum index must be set at construction time, which will allocate
19/// an area of memory of that size. As a result, this can be quite memory-consuming
20/// for sparse maps or sets, but it is as efficient as it gets for fast lookups.
21#[derive(Clone, Debug, PartialEq, Eq)]
22pub struct Array<I: Offset, T> {
23    /// The vector of elements
24    pub data: Vector<T>,
25    /// Zero-sized field to appease the compiler, since `I` is not used in any other field
26    pub phantom: PhantomData<I>,
27}
28
29impl<I: Offset, T: Clone> Array<I, T> {
30    /// Create a new array of size `size` with all elements set to `value`.
31    pub fn new(value: T, size: usize) -> Array<I, T> {
32        Array {
33            data: Vector::from_vec(vec![value; size]),
34            phantom: PhantomData,
35        }
36    }
37}
38impl<I: Offset, T> Array<I, T> {
39    /// Create a new array of size `size` without initializing its elements.
40    pub fn with_capacity(size: usize) -> Array<I, T> {
41        Array {
42            data: Vector::with_capacity(size),
43            phantom: PhantomData,
44        }
45    }
46    /// Create a new array by taking ownership of a `Vector`.
47    pub fn from(data: Vector<T>) -> Array<I, T> {
48        Array {
49            data,
50            phantom: PhantomData,
51        }
52    }
53    /// Returns the size of the array.
54    pub fn size(&self) -> usize {
55        self.data.capacity()
56    }
57}
58
59impl<I: Offset, T> Default for Array<I, T> {
60    fn default() -> Array<I, T> {
61        Array::with_capacity(0)
62    }
63}
64
65impl<I: Offset, T> Deref for Array<I, T> {
66    type Target = [T];
67    fn deref(&self) -> &[T] {
68        self.data.deref()
69    }
70}
71
72impl<I: Offset, T> DerefMut for Array<I, T> {
73    fn deref_mut(&mut self) -> &mut [T] {
74        self.data.deref_mut()
75    }
76}
77
78impl<I: Offset, T> AsRef<Array<I, T>> for Array<I, T> {
79    fn as_ref(&self) -> &Array<I, T> {
80        self
81    }
82}
83
84impl<I: Offset, T> AsMut<Array<I, T>> for Array<I, T> {
85    fn as_mut(&mut self) -> &mut Array<I, T> {
86        self
87    }
88}
89
90impl<I: Offset, T> AsRef<[T]> for Array<I, T> {
91    fn as_ref(&self) -> &[T] {
92        self
93    }
94}
95
96impl<I: Offset, T> AsMut<[T]> for Array<I, T> {
97    fn as_mut(&mut self) -> &mut [T] {
98        self
99    }
100}
101
102impl<I: Offset, T> Index<I> for Array<I, T> {
103    type Output = T;
104    fn index(&self, key: I) -> &T {
105        assert_in_bounds(0..self.size(), key.as_offset());
106        unsafe { self.data.get_unchecked(key.as_offset()) }
107    }
108}
109
110impl<I: Offset, T> IndexMut<I> for Array<I, T> {
111    fn index_mut(&mut self, key: I) -> &mut T {
112        assert_in_bounds(0..self.size(), key.as_offset());
113        unsafe { self.data.get_unchecked_mut(key.as_offset()) }
114    }
115}
116
117impl<I: Offset, T: HeapSpace> HeapSpace for Array<I, T> {
118    fn heap_space(&self) -> usize {
119        self.data.heap_space()
120            + self
121                .data
122                .iter()
123                .fold(0, |sum, item| sum + item.heap_space())
124    }
125}