kernel/mem/array.rs
1//! This module implements static and dynamic arrays for in-kernel use.
2
3use super::boxed::Box;
4use crate::utils::KernelError;
5use core::{borrow::Borrow, mem::MaybeUninit};
6
7/// This is a fixed-size map that can store up to N consecutive elements.
8pub struct IndexMap<K: Borrow<usize> + Default, V, const N: usize> {
9 data: [Option<V>; N],
10 phantom: core::marker::PhantomData<K>,
11}
12
13impl<K: Borrow<usize> + Default, V, const N: usize> IndexMap<K, V, N> {
14 /// Create a new IndexMap.
15 ///
16 /// Returns a new IndexMap.
17 pub const fn new() -> Self {
18 Self {
19 data: [const { None }; N],
20 phantom: core::marker::PhantomData,
21 }
22 }
23
24 /// Get the element at the given index.
25 ///
26 /// `index` - The index to get the element from.
27 ///
28 /// Returns `Some(&T)` if the index is in-bounds, otherwise `None`.
29 pub fn get(&self, index: &K) -> Option<&V> {
30 let index = *index.borrow();
31
32 if index < N {
33 self.data[index].as_ref()
34 } else {
35 None
36 }
37 }
38
39 /// Get a mutable reference to the element at the given index.
40 ///
41 /// `index` - The index to get the element from.
42 ///
43 /// Returns `Some(&mut T)` if the index is in-bounds, otherwise `None`.
44 pub fn get_mut(&mut self, index: &K) -> Option<&mut V> {
45 let index = *index.borrow();
46
47 if index < N {
48 self.data[index].as_mut()
49 } else {
50 None
51 }
52 }
53
54 /// Insert a value at the given index.
55 ///
56 /// `index` - The index to insert the value at.
57 /// `value` - The value to insert.
58 ///
59 /// Returns `Ok(())` if the index was in-bounds, otherwise `Err(KernelError::OutOfMemory)`.
60 pub fn insert(&mut self, index: &K, value: V) -> Result<(), KernelError> {
61 let index = *index.borrow();
62
63 if index < N {
64 self.data[index] = Some(value);
65 Ok(())
66 } else {
67 Err(KernelError::OutOfMemory)
68 }
69 }
70
71 /// Insert a value at the next available index.
72 ///
73 /// `value` - The value to insert.
74 ///
75 /// Returns `Ok(index)` if the value was inserted, otherwise `Err(KernelError::OutOfMemory)`.
76 pub fn insert_next(&mut self, value: V) -> Result<usize, KernelError> {
77 for (i, slot) in self.data.iter_mut().enumerate() {
78 if slot.is_none() {
79 *slot = Some(value);
80 return Ok(i);
81 }
82 }
83
84 Err(KernelError::OutOfMemory)
85 }
86
87 /// Remove the value at the given index.
88 ///
89 /// `index` - The index to remove the value from.
90 ///
91 /// Returns the value if it was removed, otherwise `None`.
92 pub fn remove(&mut self, index: &K) -> Option<V> {
93 let index = *index.borrow();
94
95 if index < N {
96 self.data[index].take()
97 } else {
98 None
99 }
100 }
101
102 /// Get an iterator over the elements in the map.
103 ///
104 /// Returns an iterator over the elements in the map.
105 pub fn iter(&self) -> impl Iterator<Item = &Option<V>> {
106 self.data.iter()
107 }
108
109 /// Get an cycling iterator over the elements in the map, starting from the given index.
110 ///
111 /// `index` - The index to start the iterator from.
112 ///
113 /// Returns an iterator over the elements in the map.
114 pub fn iter_from_cycle(&self, index: &K) -> impl Iterator<Item = &Option<V>> {
115 self.data.iter().cycle().skip(index.borrow() + 1)
116 }
117
118 /// Get the next index that contains a value (this will cycle).
119 ///
120 /// `index` - The index to start the search from.
121 ///
122 /// Returns the next index (potentially < index) that contains a value, otherwise `None`.
123 pub fn next(&self, index: Option<&K>) -> Option<usize> {
124 let default = K::default();
125 let index = index.unwrap_or(&default);
126
127 for (i, elem) in self.iter_from_cycle(index).enumerate() {
128 if elem.is_some() {
129 return Some((index.borrow() + i + 1) % N);
130 }
131 }
132
133 None
134 }
135
136 pub fn find_empty(&self) -> Option<usize> {
137 for (i, slot) in self.data.iter().enumerate() {
138 if slot.is_none() {
139 return Some(i);
140 }
141 }
142
143 None
144 }
145}
146
147/// This is a vector that can store up to N elements inline and will allocate on the heap if more are needed.
148pub struct Vec<T, const N: usize> {
149 len: usize,
150 data: [MaybeUninit<T>; N],
151 extra: Box<[MaybeUninit<T>]>,
152}
153
154impl<T: Clone + Copy, const N: usize> Vec<T, N> {
155 /// Create a new Vec.
156 ///
157 /// Returns a new Vec.
158 pub const fn new() -> Self {
159 Self {
160 len: 0,
161 data: [const { MaybeUninit::uninit() }; N],
162 extra: Box::new_slice_empty(),
163 }
164 }
165
166 /// Reserve additional space in the Vec.
167 ///
168 /// `additional` - The additional space to reserve.
169 ///
170 /// Returns `Ok(())` if the space was reserved, otherwise `Err(KernelError::OutOfMemory)`.
171 pub fn reserve(&mut self, additional: usize) -> Result<(), KernelError> {
172 let len_extra = self.extra.len();
173
174 // Check if we have enough space in the inline storage.
175 if self.len + additional <= N + len_extra {
176 return Ok(());
177 }
178
179 // If we don't have enough space, we need to grow the extra storage.
180 let grow = additional - N + len_extra;
181 let mut new_extra = Box::new_slice_uninit(grow)?;
182
183 // Check that the new extra storage has the requested length.
184 BUG_ON!(new_extra.len() != grow);
185
186 // Copy the old extra storage into the new one.
187 new_extra[..len_extra].copy_from_slice(&self.extra);
188
189 // Replace the old extra storage with the new one. The old one will be dropped.
190 self.extra = new_extra;
191 Ok(())
192 }
193
194 /// Reserve a fixed amount of space in the Vec. Does nothing if enough space is present already.
195 ///
196 /// `total_capacity` - The total space to be reserved.
197 ///
198 /// Returns `Ok(())` if the space was reserved, otherwise `Err(KernelError::OutOfMemory)`.
199 pub fn reserve_total_capacity(&mut self, total_capacity: usize) -> Result<(), KernelError> {
200 // Check if we already have enough space
201 if self.capacity() >= total_capacity {
202 return Ok(());
203 }
204
205 // If we don't have enough space, we need to grow the extra storage.
206 let new_out_of_line_cap = total_capacity - N;
207 let mut new_extra = Box::new_slice_uninit(new_out_of_line_cap)?;
208
209 // Check that the new extra storage has the requested length.
210 BUG_ON!(new_extra.len() != new_out_of_line_cap);
211
212 let curr_out_of_line_size = self.extra.len();
213 // Copy the old extra storage into the new one.
214 new_extra[..curr_out_of_line_size].copy_from_slice(&self.extra);
215
216 // Replace the old extra storage with the new one. The old one will be dropped.
217 self.extra = new_extra;
218 Ok(())
219 }
220
221 /// Create a new Vec with the given length and value.
222 ///
223 /// `length` - The length of the Vec.
224 /// `value` - The value to initialize the elements in the Vec with.
225 ///
226 /// Returns the new Vec or `Err(KernelError::OutOfMemory)` if the allocation failed.
227 pub fn new_init(length: usize, value: T) -> Result<Self, KernelError> {
228 let mut vec = Self::new();
229
230 // Check if we can fit all elements in the inline storage.
231 if length <= N {
232 // Initialize all elements in the inline storage.
233 for i in 0..length {
234 vec.data[i].write(value);
235 }
236 } else {
237 // Initialize all elements in the inline storage.
238 vec.data.fill(MaybeUninit::new(value));
239
240 // Check if we need to allocate extra storage.
241 if length - N > 0 {
242 // Allocate extra storage for the remaining elements.
243 let mut extra = Box::new_slice_uninit(length - N)?;
244
245 // Initialize all the required elements in the extra storage.
246 for i in N..length {
247 extra[i - N].write(value);
248 }
249
250 // Set the extra storage in the Vec.
251 vec.extra = extra;
252 }
253 }
254
255 Ok(vec)
256 }
257
258 /// Push a value onto the Vec.
259 ///
260 /// `value` - The value to push.
261 ///
262 /// Returns `Ok(())` if the value was pushed, otherwise `Err(KernelError::OutOfMemory)`.
263 pub fn push(&mut self, value: T) -> Result<(), KernelError> {
264 // Check if we have enough space in the inline storage.
265 if self.len < N {
266 // Push the value into the inline storage.
267 self.data[self.len].write(value);
268 self.len += 1;
269 Ok(())
270 } else {
271 let len_extra = self.extra.len();
272
273 // Check if we have enough space in the extra storage.
274 if self.len < N + len_extra {
275 // Push the value into the extra storage.
276 self.extra[self.len - N].write(value);
277 self.len += 1;
278 Ok(())
279 } else {
280 // We need to grow the extra storage.
281 let grow = (len_extra + 1) * 2;
282 let mut new_extra = Box::new_slice_uninit(grow)?;
283
284 BUG_ON!(new_extra.len() != grow);
285
286 // Copy the old extra storage into the new one.
287 new_extra[..len_extra].copy_from_slice(&self.extra);
288
289 // Replace the old extra storage with the new one. The old one will be dropped.
290 self.extra = new_extra;
291 self.extra[len_extra].write(value);
292 self.len += 1;
293 Ok(())
294 }
295 }
296 }
297
298 /// Pop a value from the Vec.
299 ///
300 /// Returns the value if it was popped, otherwise `None`.
301 pub fn pop(&mut self) -> Option<T> {
302 if self.len == 0 {
303 return None;
304 }
305 self.remove(self.len - 1)
306 }
307
308 /// Remove the value at the given index.
309 ///
310 /// `index` - The index to remove the value from.
311 ///
312 /// Returns the value if it was removed, otherwise `None`.
313 pub fn remove(&mut self, index: usize) -> Option<T> {
314 // Check if the index is in-bounds.
315 if index >= self.len {
316 return None;
317 }
318
319 // Get the value at the given index.
320 let value = self.at(index).cloned();
321
322 // Check if we need to move inline storage elements.
323 if index < N {
324 // Move the elements in the inline storage.
325 let end = core::cmp::min(self.len, N);
326
327 // Safety: index is less than N and min too.
328 self.data.copy_within(index + 1..end, index);
329
330 // Check if we need to move the first extra storage element into the inline storage.
331 if let Some(value) = self.at(N) {
332 self.data[end - 1].write(*value);
333 }
334
335 // Move the elements in the extra storage.
336 if self.len() > N {
337 self.extra.copy_within(1..self.len - N, 0);
338 }
339 } else {
340 // We only need to move the elements in the extra storage.
341
342 let index = index - N;
343 let end = self.len - N;
344
345 // Safety: index is less than N and min too.
346 self.extra.copy_within(index + 1..end, index);
347 }
348
349 self.len -= 1;
350 value
351 }
352
353 /// Get the length of the Vec.
354 ///
355 /// Returns the length of the Vec.
356 pub fn len(&self) -> usize {
357 self.len
358 }
359
360 /// Get the value at the given index.
361 ///
362 /// `index` - The index to get the value from.
363 ///
364 /// Returns `Some(&T)` if the index is in-bounds, otherwise `None`.
365 pub fn at(&self, index: usize) -> Option<&T> {
366 // Check if the index is in-bounds.
367 if index > self.len - 1 {
368 return None;
369 }
370
371 if index < N {
372 // Safety: the elements until self.len are initialized.
373 unsafe { Some(self.data[index].assume_init_ref()) }
374 } else {
375 let index = index - N;
376 // Safety: the elements until self.len - N are initialized.
377 unsafe { Some(self.extra[index].assume_init_ref()) }
378 }
379 }
380
381 /// Get a mutable reference to the value at the given index.
382 ///
383 /// `index` - The index to get the value from.
384 ///
385 /// Returns `Some(&mut T)` if the index is in-bounds, otherwise `None`.
386 pub fn at_mut(&mut self, index: usize) -> Option<&mut T> {
387 // Check if the index is in-bounds.
388 if index > self.len - 1 {
389 return None;
390 }
391
392 if index < N {
393 // Safety: the elements until self.len are initialized.
394 unsafe { Some(self.data[index].assume_init_mut()) }
395 } else {
396 let index = index - N;
397 // Safety: the elements until self.len - N are initialized.
398 unsafe { Some(self.extra[index].assume_init_mut()) }
399 }
400 }
401
402 /// Swap the values at the given indices.
403 ///
404 /// `a` - The first index.
405 /// `b` - The second index.
406 pub fn swap(&mut self, a: usize, b: usize) {
407 // Check if the indices are in-bounds.
408 if a >= self.len || b >= self.len {
409 return;
410 }
411
412 if a < N && b < N {
413 // Both indices are in the inline storage.
414 self.data.swap(a, b);
415 } else if a >= N && b >= N {
416 // Both indices are in the extra storage.
417 self.extra.swap(a - N, b - N);
418 } else if a >= N {
419 // The first index is in the extra storage.
420 core::mem::swap(&mut self.extra[a - N], &mut self.data[b]);
421 } else {
422 // The second index is in the extra storage.
423 core::mem::swap(&mut self.data[a], &mut self.extra[b - N]);
424 }
425 }
426
427 /// Check if the Vec is empty.
428 ///
429 /// Returns `true` if the Vec is empty, otherwise `false`.
430 pub fn is_empty(&self) -> bool {
431 self.len == 0
432 }
433
434 /// Get total amount of space in Vec (in- and out-of-line)
435 ///
436 /// Returns total amount of reserved space in the vec
437 pub fn capacity(&self) -> usize {
438 N + self.extra.len()
439 }
440}
441
442impl<T, const N: usize> Drop for Vec<T, N> {
443 fn drop(&mut self) {
444 let min = core::cmp::min(self.len, N);
445
446 // Drop all elements in the inline storage.
447 for elem in &mut self.data[0..min] {
448 // Safety: the elements until min are initialized.
449 unsafe {
450 elem.assume_init_drop();
451 }
452 }
453
454 // Drop all elements in the extra storage.
455 for elem in &mut (*self.extra)[0..self.len - N] {
456 // Safety: the elements until self.len - N are initialized.
457 unsafe {
458 elem.assume_init_drop();
459 }
460 }
461 }
462}
463
464#[cfg(kani)]
465mod verification {
466 use super::*;
467}