Skip to main content

fbl/
vector.rs

1// Copyright 2026 The Fuchsia Authors
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT
6
7use core::ops::{Deref, DerefMut};
8use kalloc::{AllocError, Allocator, Box, DefaultAllocator};
9
10/// Macro to construct a fallible `Vector`.
11///
12/// This macro is analogous to the standard `vec!` macro but returns an
13/// `Option<Vector<T>>` to handle allocation failures gracefully.
14///
15/// # Returns
16/// - `Some(Vector<T>)` on successful allocation.
17/// - `None` if allocation fails.
18///
19/// # Examples
20///
21/// ```
22/// use fbl::try_vec;
23///
24/// // Constructing a vector with a list of elements:
25/// let v = try_vec![1, 2, 3].expect("Allocation failed");
26/// assert_eq!(v.len(), 3);
27///
28/// // Constructing a vector with a repeated element:
29/// let v2 = try_vec![0; 5].expect("Allocation failed");
30/// assert_eq!(v2.len(), 5);
31/// assert_eq!(v2[0], 0);
32/// ```
33#[macro_export]
34macro_rules! try_vec {
35    ($($x:expr),* $(,)?) => {
36        {
37            let mut v = $crate::Vector::new();
38            let count = 0 $(+ { let _ = stringify!($x); 1 })*;
39            let f = || {
40                if count > 0 {
41                    v.reserve(count)?;
42                }
43                $(
44                    v.push_back($x)?;
45                )*
46                Ok(v)
47            };
48            f()
49        }
50    };
51
52    ($elem:expr; $n:expr) => {
53        {
54            let mut v = $crate::Vector::new();
55            let n = $n;
56            let f = || {
57                if n > 0 {
58                    v.reserve(n)?;
59                    for _ in 0..n {
60                        v.push_back($elem.clone())?;
61                    }
62                }
63                Ok(v)
64            };
65            f()
66        }
67    };
68}
69
70/// `Vector` is a heap-allocated dynamic array, providing a subset of the
71/// functionality of `std::vec::Vec`.
72///
73/// Notably, `Vector` supports fallible allocation (methods return `Option`
74/// on allocation failure) to handle out-of-memory conditions gracefully,
75/// which is required for Zircon kernel code.
76///
77/// `Vector` does not implement `Clone` and cannot be copied.
78pub struct Vector<T, A: Allocator = DefaultAllocator> {
79    buf: Box<[core::mem::MaybeUninit<T>], A>,
80
81    /// The number of entries in the vector.
82    ///
83    /// This struct maintains the invariant that the elements ..size of `buf`
84    /// are initialized.
85    size: usize,
86}
87
88const CAPACITY_MINIMUM: usize = 16;
89const CAPACITY_GROWTH_FACTOR: usize = 2;
90const CAPACITY_SHRINK_FACTOR: usize = 4;
91
92// Size of Vector is now 24 bytes (Box (16) + size (8))
93zr::static_assert!(core::mem::size_of::<Vector<u32>>() == 24);
94zr::static_assert!(core::mem::align_of::<Vector<u32>>() == 8);
95
96impl<T, A: Allocator> Vector<T, A> {
97    /// Creates an empty vector with the given allocator.
98    pub const fn new_in(allocator: A) -> Self {
99        Vector { buf: Box::empty_slice_in(allocator), size: 0 }
100    }
101
102    /// Returns the number of elements in the vector.
103    pub fn len(&self) -> usize {
104        self.size
105    }
106
107    /// Returns the capacity of the vector.
108    pub fn capacity(&self) -> usize {
109        self.buf.len()
110    }
111
112    /// Returns true if the vector is empty.
113    pub fn is_empty(&self) -> bool {
114        self.size == 0
115    }
116
117    /// Reserve enough size to hold at least capacity elements.
118    pub fn reserve(&mut self, new_capacity: usize) -> Result<(), AllocError> {
119        if new_capacity <= self.buf.len() {
120            return Ok(());
121        }
122        self.reallocate(new_capacity)
123    }
124
125    /// Clears the vector, dropping all elements.
126    pub fn clear(&mut self) {
127        self.truncate(0);
128    }
129
130    /// Swaps the contents of this vector with another.
131    pub fn swap(&mut self, other: &mut Self) {
132        core::mem::swap(self, other);
133    }
134
135    /// Appends an element to the back of the vector.
136
137    pub fn push_back(&mut self, value: T) -> Result<(), AllocError> {
138        self.grow_for_new_element()?;
139        self.buf[self.size].write(value);
140        self.size += 1;
141        Ok(())
142    }
143
144    /// Removes the last element from the vector and returns it, or None if it is empty.
145    pub fn pop_back(&mut self) -> Option<T> {
146        if self.is_empty() {
147            return None;
148        }
149        self.size -= 1;
150        // SAFETY: We checked that the vector is not empty, and we decremented
151        // size. So `self.size` is a valid index containing an initialized element.
152        let val = unsafe { self.buf[self.size].assume_init_read() };
153        self.consider_shrinking();
154        Some(val)
155    }
156
157    /// Inserts an element at position index, shifting all elements after it to the right.
158
159    pub fn insert(&mut self, index: usize, value: T) -> Result<(), AllocError> {
160        assert!(index <= self.size);
161        self.push_back(value)?;
162        let size = self.size;
163        self[index..size].rotate_right(1);
164        Ok(())
165    }
166
167    /// Removes the element at position index, shifting all elements after it to the left.
168    pub fn erase(&mut self, index: usize) -> T {
169        assert!(index < self.size);
170        let size = self.size;
171        self[index..size].rotate_left(1);
172        self.pop_back().unwrap()
173    }
174
175    /// Shortens the vector, keeping the first `new_len` elements and dropping the rest.
176    /// If `new_len` is greater than or equal to the current size, this has no effect.
177    pub fn truncate(&mut self, new_len: usize) {
178        if new_len >= self.size {
179            return;
180        }
181        let old_size = self.size;
182        self.size = new_len;
183        // SAFETY: Elements from new_len to old_size are initialized.
184        unsafe {
185            core::ptr::drop_in_place(self.buf[new_len..old_size].assume_init_mut());
186        }
187        self.consider_shrinking();
188    }
189
190    /// Resizes the vector to the specified size.
191    /// If new_size is smaller, elements are truncated.
192    /// If new_size is larger, new elements are initialized with `Default::default()`.
193    /// Returns None if allocation fails.
194
195    pub fn resize_with_default(&mut self, new_size: usize) -> Result<(), AllocError>
196    where
197        T: Default,
198    {
199        self.resize_with(new_size, T::default)
200    }
201
202    /// Resizes the vector to the specified size.
203    /// If new_size is smaller, elements are truncated.
204    /// If new_size is larger, new elements are cloned from `value`.
205    /// Returns None if allocation fails.
206
207    pub fn resize(&mut self, new_size: usize, value: T) -> Result<(), AllocError>
208    where
209        T: Clone,
210    {
211        self.resize_with(new_size, || value.clone())
212    }
213
214    /// Resizes the vector to the specified size.
215    /// If new_size is smaller, elements are truncated.
216    /// If new_size is larger, new elements are created by calling the closure.
217    /// Returns None if allocation fails.
218
219    pub fn resize_with<F>(&mut self, new_size: usize, mut f: F) -> Result<(), AllocError>
220    where
221        F: FnMut() -> T,
222    {
223        if new_size <= self.size {
224            self.truncate(new_size);
225        } else {
226            self.reserve(new_size)?;
227            while self.size < new_size {
228                self.push_back(f())?;
229            }
230        }
231        Ok(())
232    }
233
234    // Internal helper to reallocate storage.
235    fn reallocate(&mut self, new_capacity: usize) -> Result<(), AllocError> {
236        assert!(new_capacity > 0);
237        assert!(new_capacity >= self.size);
238
239        if new_capacity > self.buf.len() {
240            Box::try_grow(&mut self.buf, new_capacity)?;
241        } else if new_capacity < self.buf.len() {
242            // SAFETY: We ensure in Vector that elements above `new_capacity`
243            // are uninitialized or already dropped.
244            unsafe {
245                Box::try_shrink(&mut self.buf, new_capacity)?;
246            }
247        }
248        Ok(())
249    }
250
251    // Internal helper to grow capacity if needed for a new element.
252
253    fn grow_for_new_element(&mut self) -> Result<(), AllocError> {
254        if self.size == self.buf.len() {
255            let new_capacity = if self.buf.len() == 0 {
256                CAPACITY_MINIMUM
257            } else {
258                self.buf.len() * CAPACITY_GROWTH_FACTOR
259            };
260            self.reallocate(new_capacity)?;
261        }
262        Ok(())
263    }
264
265    // Internal helper to shrink capacity if it's too large.
266    fn consider_shrinking(&mut self) {
267        if self.size * CAPACITY_SHRINK_FACTOR < self.buf.len() && self.buf.len() > CAPACITY_MINIMUM
268        {
269            let new_capacity = self.buf.len() / CAPACITY_SHRINK_FACTOR;
270            // If reallocation fails, we just keep the old capacity.
271            let _ = self.reallocate(new_capacity);
272        }
273    }
274
275    /// Creates a vector from an iterator.
276    /// Returns None if allocation fails.
277
278    /// Creates a vector from an iterator with the given allocator.
279    pub fn try_from_iter_in<I: IntoIterator<Item = T>>(
280        iter: I,
281        allocator: A,
282    ) -> Result<Self, AllocError> {
283        let mut v = Vector::new_in(allocator);
284        let iter = iter.into_iter();
285
286        let (lower, _) = iter.size_hint();
287        if lower > 0 {
288            v.reserve(lower)?;
289        }
290
291        for item in iter {
292            v.push_back(item)?;
293        }
294        Ok(v)
295    }
296}
297
298impl<T, A: Allocator> Deref for Vector<T, A> {
299    type Target = [T];
300
301    fn deref(&self) -> &Self::Target {
302        // SAFETY: Vector maintains the invariant that elements from 0 to self.size are initialized.
303        unsafe { self.buf[0..self.size].assume_init_ref() }
304    }
305}
306
307impl<T, A: Allocator> DerefMut for Vector<T, A> {
308    fn deref_mut(&mut self) -> &mut Self::Target {
309        // SAFETY: Vector maintains the invariant that elements from 0 to self.size are initialized.
310        unsafe { self.buf[0..self.size].assume_init_mut() }
311    }
312}
313
314impl<T, A: Allocator> Drop for Vector<T, A> {
315    fn drop(&mut self) {
316        self.clear();
317    }
318}
319
320impl<T> Vector<T, DefaultAllocator> {
321    /// Creates an empty vector using the default allocator.
322    pub const fn new() -> Self {
323        Vector { buf: Box::empty_slice(), size: 0 }
324    }
325
326    /// Creates a vector from an iterator using the default allocator.
327    pub fn try_from_iter<I: IntoIterator<Item = T>>(iter: I) -> Result<Self, AllocError> {
328        let mut v = Vector::new();
329        let iter = iter.into_iter();
330
331        let (lower, _) = iter.size_hint();
332        if lower > 0 {
333            v.reserve(lower)?;
334        }
335
336        for item in iter {
337            v.push_back(item)?;
338        }
339        Ok(v)
340    }
341}
342
343impl<T> Default for Vector<T, DefaultAllocator> {
344    fn default() -> Self {
345        Self::new()
346    }
347}
348
349#[cfg(test)]
350mod tests {
351    extern crate std;
352
353    use super::*;
354
355    use core::cell::Cell;
356    use core::ptr::NonNull;
357
358    #[derive(Debug, PartialEq, Eq)]
359    struct TestState {
360        live_obj_count: Cell<usize>,
361        ctor_count: Cell<usize>,
362        dtor_count: Cell<usize>,
363        alloc_count: Cell<usize>,
364        fail_threshold: Cell<usize>,
365    }
366
367    impl Default for TestState {
368        fn default() -> Self {
369            Self {
370                live_obj_count: Cell::new(0),
371                ctor_count: Cell::new(0),
372                dtor_count: Cell::new(0),
373                alloc_count: Cell::new(0),
374                fail_threshold: Cell::new(usize::MAX),
375            }
376        }
377    }
378
379    #[derive(Clone)]
380    struct TestAllocator<'a> {
381        state: &'a TestState,
382    }
383
384    impl<'a> Allocator for TestAllocator<'a> {
385        fn allocate(&self, layout: core::alloc::Layout) -> Result<NonNull<[u8]>, AllocError> {
386            let current = self.state.alloc_count.get();
387            self.state.alloc_count.set(current + 1);
388            if current >= self.state.fail_threshold.get() {
389                return Err(AllocError);
390            }
391            DefaultAllocator::default().allocate(layout)
392        }
393
394        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: core::alloc::Layout) {
395            unsafe { DefaultAllocator::default().deallocate(ptr, layout) }
396        }
397
398        unsafe fn grow(
399            &self,
400            ptr: NonNull<u8>,
401            old_layout: core::alloc::Layout,
402            new_layout: core::alloc::Layout,
403        ) -> Result<NonNull<[u8]>, AllocError> {
404            let current = self.state.alloc_count.get();
405            self.state.alloc_count.set(current + 1);
406            if current >= self.state.fail_threshold.get() {
407                return Err(AllocError);
408            }
409            unsafe { DefaultAllocator::default().grow(ptr, old_layout, new_layout) }
410        }
411
412        unsafe fn shrink(
413            &self,
414            ptr: NonNull<u8>,
415            old_layout: core::alloc::Layout,
416            new_layout: core::alloc::Layout,
417        ) -> Result<NonNull<[u8]>, AllocError> {
418            let current = self.state.alloc_count.get();
419            self.state.alloc_count.set(current + 1);
420            if current >= self.state.fail_threshold.get() {
421                return Err(AllocError);
422            }
423            unsafe { DefaultAllocator::default().shrink(ptr, old_layout, new_layout) }
424        }
425
426        fn allocate_zeroed(
427            &self,
428            layout: core::alloc::Layout,
429        ) -> Result<NonNull<[u8]>, AllocError> {
430            let current = self.state.alloc_count.get();
431            self.state.alloc_count.set(current + 1);
432            if current >= self.state.fail_threshold.get() {
433                return Err(AllocError);
434            }
435            DefaultAllocator::default().allocate_zeroed(layout)
436        }
437    }
438
439    #[derive(Debug, Eq, PartialEq)]
440    struct TestObject<'a> {
441        val: usize,
442        alive: bool,
443        state: &'a TestState,
444    }
445
446    impl<'a> TestObject<'a> {
447        fn new(val: usize, state: &'a TestState) -> Self {
448            state.live_obj_count.set(state.live_obj_count.get() + 1);
449            state.ctor_count.set(state.ctor_count.get() + 1);
450            TestObject { val, alive: true, state }
451        }
452    }
453
454    impl<'a> Drop for TestObject<'a> {
455        fn drop(&mut self) {
456            if self.alive {
457                self.state.live_obj_count.set(self.state.live_obj_count.get() - 1);
458                self.state.dtor_count.set(self.state.dtor_count.get() + 1);
459            }
460        }
461    }
462
463    #[test]
464    fn test_empty() {
465        let v: Vector<u32> = Vector::new();
466        assert_eq!(v.len(), 0);
467        assert_eq!(v.capacity(), 0);
468        assert!(v.is_empty());
469    }
470
471    #[test]
472    fn test_push_pop() {
473        let mut v: Vector<u32> = Vector::new();
474        v.push_back(1).unwrap();
475        v.push_back(2).unwrap();
476        v.push_back(3).unwrap();
477
478        assert_eq!(v.len(), 3);
479        assert_eq!(v[0], 1);
480        assert_eq!(v[1], 2);
481        assert_eq!(v[2], 3);
482
483        assert_eq!(v.pop_back(), Some(3));
484        assert_eq!(v.pop_back(), Some(2));
485        assert_eq!(v.pop_back(), Some(1));
486        assert_eq!(v.pop_back(), None);
487    }
488
489    #[test]
490    fn test_insert_erase() {
491        let mut v: Vector<u32> = Vector::new();
492        v.push_back(1).unwrap();
493        v.push_back(3).unwrap();
494
495        v.insert(1, 2).unwrap();
496        assert_eq!(v.len(), 3);
497        assert_eq!(v[0], 1);
498        assert_eq!(v[1], 2);
499        assert_eq!(v[2], 3);
500
501        assert_eq!(v.erase(1), 2);
502        assert_eq!(v.len(), 2);
503        assert_eq!(v[0], 1);
504        assert_eq!(v[1], 3);
505    }
506
507    #[test]
508    fn test_resize() {
509        let mut v: Vector<u32> = Vector::new();
510        v.resize_with_default(5).unwrap();
511        assert_eq!(v.len(), 5);
512        for i in 0..5 {
513            assert_eq!(v[i], 0);
514        }
515
516        v.resize_with_default(2).unwrap();
517        assert_eq!(v.len(), 2);
518    }
519
520    #[test]
521    fn test_drop_behavior() {
522        let state = TestState::default();
523        {
524            let mut v: Vector<TestObject<'_>, TestAllocator<'_>> =
525                Vector::new_in(TestAllocator { state: &state });
526            v.push_back(TestObject::new(1, &state)).unwrap();
527            v.push_back(TestObject::new(2, &state)).unwrap();
528            assert_eq!(state.live_obj_count.get(), 2);
529        }
530        assert_eq!(state.live_obj_count.get(), 0);
531        assert_eq!(state.ctor_count.get(), 2);
532        assert_eq!(state.dtor_count.get(), 2);
533    }
534
535    #[test]
536    fn test_counting_allocator() {
537        let state = TestState::default();
538        {
539            let mut v: Vector<u32, TestAllocator<'_>> =
540                Vector::new_in(TestAllocator { state: &state });
541            v.push_back(1).unwrap(); // Causes allocation
542            assert_eq!(state.alloc_count.get(), 1);
543        }
544    }
545
546    #[test]
547    fn test_failing_allocator() {
548        let state = TestState::default();
549        state.fail_threshold.set(1); // Fail after 1st allocation
550
551        let mut v: Vector<u32, TestAllocator<'_>> = Vector::new_in(TestAllocator { state: &state });
552        v.push_back(1).unwrap(); // 1st alloc succeeds
553
554        // Fill up to capacity to trigger grow
555        for i in 2..=16 {
556            v.push_back(i).unwrap();
557        }
558        assert_eq!(v.len(), 16);
559        assert_eq!(v.capacity(), 16);
560
561        // Next push_back will try to grow and call alloc.
562        // Since threshold is 1, and we already did 1 alloc (at first push),
563        // next alloc will fail!
564        assert_eq!(v.push_back(17), Err(AllocError));
565        assert_eq!(v.len(), 16); // Size unchanged
566
567        // Verify elements are still valid
568        for i in 0..16 {
569            assert_eq!(v[i], (i + 1) as u32);
570        }
571    }
572
573    #[test]
574    fn test_truncate() {
575        let mut v: Vector<u32> = Vector::new();
576        v.push_back(1).unwrap();
577        v.push_back(2).unwrap();
578        v.push_back(3).unwrap();
579
580        v.truncate(2);
581        assert_eq!(v.len(), 2);
582        assert_eq!(v[0], 1);
583        assert_eq!(v[1], 2);
584
585        v.truncate(5); // No effect
586        assert_eq!(v.len(), 2);
587    }
588
589    #[test]
590    fn test_truncate_drops_elements() {
591        let state = TestState::default();
592        {
593            let mut v: Vector<TestObject<'_>, TestAllocator<'_>> =
594                Vector::new_in(TestAllocator { state: &state });
595            v.push_back(TestObject::new(1, &state)).unwrap();
596            v.push_back(TestObject::new(2, &state)).unwrap();
597            v.push_back(TestObject::new(3, &state)).unwrap();
598
599            assert_eq!(state.live_obj_count.get(), 3);
600
601            v.truncate(1);
602            assert_eq!(v.len(), 1);
603            assert_eq!(state.live_obj_count.get(), 1);
604            assert_eq!(state.dtor_count.get(), 2);
605        }
606        assert_eq!(state.live_obj_count.get(), 0);
607    }
608
609    #[test]
610    fn test_iterator() {
611        let mut v: Vector<u32> = Vector::new();
612        v.push_back(1).unwrap();
613        v.push_back(2).unwrap();
614
615        let mut it = v.iter();
616        assert_eq!(it.next(), Some(&1));
617        assert_eq!(it.next(), Some(&2));
618        assert_eq!(it.next(), None);
619
620        for x in v.iter_mut() {
621            *x += 10;
622        }
623
624        assert_eq!(v[0], 11);
625        assert_eq!(v[1], 12);
626    }
627
628    #[test]
629    fn test_box() {
630        let state = TestState::default();
631        {
632            let mut v: Vector<Box<TestObject<'_>, TestAllocator<'_>>, TestAllocator<'_>> =
633                Vector::new_in(TestAllocator { state: &state });
634            v.push_back(
635                Box::try_new_in(TestObject::new(1, &state), TestAllocator { state: &state })
636                    .unwrap(),
637            )
638            .unwrap();
639            assert_eq!(v.len(), 1);
640            assert_eq!(v[0].val, 1);
641        }
642    }
643
644    #[test]
645    fn test_try_from_iter() {
646        let items = [1, 2, 3, 4, 5];
647        let v: Vector<u32> = Vector::try_from_iter(items.iter().copied()).unwrap();
648        assert_eq!(v.len(), 5);
649        assert_eq!(v[0], 1);
650        assert_eq!(v[4], 5);
651    }
652
653    #[test]
654    fn test_try_from_iter_failing() {
655        let state = TestState::default();
656        state.fail_threshold.set(0); // Fail immediately
657
658        let items = [1, 2, 3, 4, 5];
659        let v: Result<Vector<u32, TestAllocator<'_>>, AllocError> =
660            Vector::try_from_iter_in(items.iter().copied(), TestAllocator { state: &state });
661        assert!(v.is_err());
662    }
663
664    #[test]
665    fn test_try_vec_macro() {
666        let v: Result<Vector<u32>, AllocError> = try_vec![1, 2, 3];
667        let v = v.unwrap();
668        assert_eq!(v.len(), 3);
669        assert_eq!(v[0], 1);
670        assert_eq!(v[2], 3);
671
672        let v2: Result<Vector<u32>, AllocError> = try_vec![0; 5];
673        let v2 = v2.unwrap();
674        assert_eq!(v2.len(), 5);
675        for i in 0..5 {
676            assert_eq!(v2[i], 0);
677        }
678    }
679
680    #[test]
681    fn test_try_vec_macro_failing() {
682        let state = TestState::default();
683        state.fail_threshold.set(0); // Fail immediately
684
685        let mut v: Vector<u32, TestAllocator<'_>> = Vector::new_in(TestAllocator { state: &state });
686        assert!(v.push_back(1).is_err());
687    }
688
689    #[test]
690    fn test_swap() {
691        let v1: Result<Vector<u32>, AllocError> = try_vec![1, 2, 3];
692        let mut v1 = v1.unwrap();
693        let v2: Result<Vector<u32>, AllocError> = try_vec![4, 5];
694        let mut v2 = v2.unwrap();
695
696        v1.swap(&mut v2);
697
698        assert_eq!(v1.len(), 2);
699        assert_eq!(v1[0], 4);
700        assert_eq!(v1[1], 5);
701
702        assert_eq!(v2.len(), 3);
703        assert_eq!(v2[0], 1);
704        assert_eq!(v2[1], 2);
705        assert_eq!(v2[2], 3);
706    }
707
708    #[test]
709    fn test_resize_with_value() {
710        let mut v: Vector<u32> = Vector::new();
711        v.resize(3, 42).unwrap();
712        assert_eq!(v.len(), 3);
713        assert_eq!(v[0], 42);
714        assert_eq!(v[1], 42);
715        assert_eq!(v[2], 42);
716
717        v.resize(1, 10).unwrap();
718        assert_eq!(v.len(), 1);
719        assert_eq!(v[0], 42); // Original element preserved
720    }
721
722    #[test]
723    fn test_resize_with() {
724        let mut v: Vector<u32> = Vector::new();
725        let mut c = 0;
726        v.resize_with(3, || {
727            c += 1;
728            c
729        })
730        .unwrap();
731        assert_eq!(v.len(), 3);
732        assert_eq!(v[0], 1);
733        assert_eq!(v[1], 2);
734        assert_eq!(v[2], 3);
735    }
736}