orx_split_vec/common_traits/index.rs
1use crate::{Growth, SplitVec};
2use core::ops::{Index, IndexMut};
3
4impl<T, G> Index<usize> for SplitVec<T, G>
5where
6 G: Growth,
7{
8 type Output = T;
9
10 /// Returns a reference to the `index`-th item of the vector.
11 ///
12 /// # Panics
13 ///
14 /// Panics if `index` is out of bounds.
15 ///
16 /// # Examples
17 ///
18 /// ```
19 /// use orx_split_vec::*;
20 ///
21 /// let mut vec = SplitVec::with_linear_growth(4);
22 ///
23 /// vec.extend_from_slice(&[0, 1, 2, 3]);
24 ///
25 /// assert_eq!(&1, &vec[1]);
26 /// assert_eq!(&3, &vec[3]);
27 /// // let x = &vec[4]; // panics!
28 /// ```
29 fn index(&self, index: usize) -> &Self::Output {
30 let (f, i) = self
31 .get_fragment_and_inner_indices(index)
32 .expect("index is out of bounds");
33 &self.fragments[f][i]
34 }
35}
36
37impl<T, G> IndexMut<usize> for SplitVec<T, G>
38where
39 G: Growth,
40{
41 /// Returns a mutable reference to the `index`-th item of the vector.
42 ///
43 /// # Panics
44 ///
45 /// Panics if `index` is out of bounds.
46 ///
47 /// # Examples
48 ///
49 /// ```
50 /// use orx_split_vec::*;
51 ///
52 /// let mut vec = SplitVec::with_linear_growth(2);
53 ///
54 /// vec.extend_from_slice(&[0, 1, 2, 3]);
55 ///
56 /// let item2 = &mut vec[2];
57 /// *item2 = 42;
58 /// assert_eq!(vec, &[0, 1, 42, 3]);
59 ///
60 /// // let x = &mut vec[4]; // panics!
61 /// ```
62 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
63 let (f, i) = self
64 .get_fragment_and_inner_indices(index)
65 .expect("index is out of bounds");
66 &mut self.fragments[f][i]
67 }
68}
69
70impl<T, G> Index<(usize, usize)> for SplitVec<T, G>
71where
72 G: Growth,
73{
74 type Output = T;
75
76 /// One can treat the split vector as a jagged array
77 /// and access an item with (fragment_index, inner_fragment_index)
78 /// if these numbers are known.
79 ///
80 /// # Panics
81 ///
82 /// Panics if:
83 ///
84 /// * `fragment_and_inner_index.0` is not a valid fragment index; i.e., not within `0..self.fragments().len()`, or
85 /// * `fragment_and_inner_index.1` is not a valid index for the corresponding fragment; i.e., not within `0..self.fragments()[fragment_and_inner_index.0].len()`.
86 ///
87 /// # Examples
88 ///
89 /// Assume that we create a split vector with a constant growth of N elements.
90 /// This means that each fraction will have a capacity and max-length of N.
91 ///
92 /// Then, the fragment and inner index of the element with index `i` can be computed as
93 /// `(i / N, i % N)`.
94 ///
95 /// ```
96 /// use orx_split_vec::*;
97 ///
98 /// let mut vec = SplitVec::with_linear_growth(2);
99 ///
100 /// for i in 0..10 {
101 /// vec.push(i);
102 /// }
103 ///
104 /// // layout of the data will be as follows:
105 /// // fragment-0: [0, 1, 2, 3]
106 /// // fragment-1: [4, 5, 6, 7]
107 /// // fragment-2: [8, 9]
108 ///
109 /// assert_eq!(1, vec[(0, 1)]);
110 /// assert_eq!(7, vec[(1, 3)]);
111 /// assert_eq!(8, vec[(2, 0)]);
112 ///
113 /// // since we know the layout, we can define the index transformer for direct access
114 /// fn fragment_and_inner_idx(index: usize) -> (usize, usize) {
115 /// (index / 4, index % 4)
116 /// }
117 ///
118 /// for index in 0..vec.len() {
119 /// let split_access = &vec[index];
120 /// let direct_access = &vec[fragment_and_inner_idx(index)];
121 /// assert_eq!(split_access, direct_access);
122 /// }
123 ///
124 /// ```
125 fn index(&self, fragment_and_inner_index: (usize, usize)) -> &Self::Output {
126 &self.fragments[fragment_and_inner_index.0][fragment_and_inner_index.1]
127 }
128}
129impl<T, G> IndexMut<(usize, usize)> for SplitVec<T, G>
130where
131 G: Growth,
132{
133 /// One can treat the split vector as a jagged array
134 /// and access an item with (fragment_index, inner_fragment_index)
135 /// if these numbers are known.
136 ///
137 /// # Panics
138 ///
139 /// Panics if:
140 ///
141 /// * `fragment_and_inner_index.0` is not a valid fragment index; i.e., not within `0..self.fragments().len()`, or
142 /// * `fragment_and_inner_index.1` is not a valid index for the corresponding fragment; i.e., not within `0..self.fragments()[fragment_and_inner_index.0].len()`.
143 ///
144 /// # Examples
145 ///
146 /// Assume that we create a split vector with a constant growth of N elements.
147 /// This means that each fraction will have a capacity and max-length of N.
148 ///
149 /// Then, the fragment and inner index of the element with index `i` can be computed as
150 /// `(i / N, i % N)`.
151 ///
152 /// ```
153 /// use orx_split_vec::*;
154 ///
155 /// let mut vec = SplitVec::with_linear_growth(2);
156 ///
157 /// for i in 0..10 {
158 /// vec.push(i);
159 /// }
160 ///
161 /// // layout of the data will be as follows:
162 /// // fragment-0: [0, 1, 2, 3]
163 /// // fragment-1: [4, 5, 6, 7]
164 /// // fragment-2: [8, 9]
165 ///
166 /// vec[(0, 1)] += 100; // 1 -> 101
167 /// vec[(1, 3)] += 100; // 7 -> 107
168 /// vec[(2, 0)] += 100; // 8 -> 108
169 /// assert_eq!(vec, &[0, 101, 2, 3, 4, 5, 6, 107, 108, 9]);
170 ///
171 /// // since we know the layout, we can define the index transformer for direct access
172 /// fn fragment_and_inner_idx(index: usize) -> (usize, usize) {
173 /// (index / 4, index % 4)
174 /// }
175 ///
176 /// for index in 0..vec.len() {
177 /// let direct_access = &mut vec[fragment_and_inner_idx(index)];
178 /// if *direct_access < 100 {
179 /// *direct_access += 100;
180 /// }
181 /// }
182 /// assert_eq!(vec, &[100, 101, 102, 103, 104, 105, 106, 107, 108, 109]);
183 ///
184 /// ```
185 fn index_mut(&mut self, fragment_and_inner_index: (usize, usize)) -> &mut Self::Output {
186 &mut self.fragments[fragment_and_inner_index.0][fragment_and_inner_index.1]
187 }
188}
189
190#[cfg(test)]
191mod tests {
192 use crate::test_all_growth_types;
193 use crate::*;
194 use alloc::vec::Vec;
195
196 #[test]
197 fn index() {
198 fn test<G: Growth>(mut vec: SplitVec<usize, G>) {
199 vec.extend_from_slice(&(0..21).collect::<Vec<_>>());
200 vec.extend_from_slice(&(21..33).collect::<Vec<_>>());
201 vec.extend_from_slice(&(33..50).collect::<Vec<_>>());
202
203 assert_eq!(50, vec.len());
204 for i in 0..50 {
205 assert_eq!(i, vec[i]);
206 vec[i] += 50;
207 }
208 for i in 0..50 {
209 assert_eq!(50 + i, vec[i]);
210 }
211 }
212 test_all_growth_types!(test);
213 }
214
215 #[test]
216 fn double_indices() {
217 fn test<G: Growth>(mut vec: SplitVec<usize, G>) {
218 vec.extend_from_slice(&(0..21).collect::<Vec<_>>());
219 vec.extend_from_slice(&(21..33).collect::<Vec<_>>());
220 vec.extend_from_slice(&(33..50).collect::<Vec<_>>());
221
222 assert_eq!(50, vec.len());
223 for i in 0..50 {
224 let (f, j) = vec.get_fragment_and_inner_indices(i).expect("is-some");
225 assert_eq!(i, vec[(f, j)]);
226 vec[(f, j)] += 50;
227 }
228 for i in 0..50 {
229 let (f, j) = vec.get_fragment_and_inner_indices(i).expect("is-some");
230 assert_eq!(50 + i, vec[(f, j)]);
231 }
232 }
233 test_all_growth_types!(test);
234 }
235}