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    pub fn push_back(&mut self, value: T) -> Result<(), AllocError> {
137        self.grow_for_new_element()?;
138        self.buf[self.size].write(value);
139        self.size += 1;
140        Ok(())
141    }
142
143    /// Removes the last element from the vector and returns it, or None if it is empty.
144    pub fn pop_back(&mut self) -> Option<T> {
145        if self.is_empty() {
146            return None;
147        }
148        self.size -= 1;
149        // SAFETY: We checked that the vector is not empty, and we decremented
150        // size. So `self.size` is a valid index containing an initialized element.
151        let val = unsafe { self.buf[self.size].assume_init_read() };
152        self.consider_shrinking();
153        Some(val)
154    }
155
156    /// Inserts an element at position index, shifting all elements after it to the right.
157    pub fn insert(&mut self, index: usize, value: T) -> Result<(), AllocError> {
158        assert!(index <= self.size);
159        self.push_back(value)?;
160        let size = self.size;
161        self[index..size].rotate_right(1);
162        Ok(())
163    }
164
165    /// Removes the element at position index, shifting all elements after it to the left.
166    pub fn erase(&mut self, index: usize) -> T {
167        assert!(index < self.size);
168        let size = self.size;
169        self[index..size].rotate_left(1);
170        self.pop_back().unwrap()
171    }
172
173    /// Shortens the vector, keeping the first `new_len` elements and dropping the rest.
174    /// If `new_len` is greater than or equal to the current size, this has no effect.
175    pub fn truncate(&mut self, new_len: usize) {
176        if new_len >= self.size {
177            return;
178        }
179        let old_size = self.size;
180        self.size = new_len;
181        // SAFETY: Elements from new_len to old_size are initialized.
182        unsafe {
183            core::ptr::drop_in_place(self.buf[new_len..old_size].assume_init_mut());
184        }
185        self.consider_shrinking();
186    }
187
188    /// Resizes the vector to the specified size.
189    /// If new_size is smaller, elements are truncated.
190    /// If new_size is larger, new elements are initialized with `Default::default()`.
191    /// Returns None if allocation fails.
192    pub fn resize_with_default(&mut self, new_size: usize) -> Result<(), AllocError>
193    where
194        T: Default,
195    {
196        self.resize_with(new_size, T::default)
197    }
198
199    /// Resizes the vector to the specified size.
200    /// If new_size is smaller, elements are truncated.
201    /// If new_size is larger, new elements are cloned from `value`.
202    /// Returns None if allocation fails.
203    pub fn resize(&mut self, new_size: usize, value: T) -> Result<(), AllocError>
204    where
205        T: Clone,
206    {
207        self.resize_with(new_size, || value.clone())
208    }
209
210    /// Resizes the vector to the specified size.
211    /// If new_size is smaller, elements are truncated.
212    /// If new_size is larger, new elements are created by calling the closure.
213    /// Returns None if allocation fails.
214    pub fn resize_with<F>(&mut self, new_size: usize, mut f: F) -> Result<(), AllocError>
215    where
216        F: FnMut() -> T,
217    {
218        if new_size <= self.size {
219            self.truncate(new_size);
220        } else {
221            self.reserve(new_size)?;
222            while self.size < new_size {
223                self.push_back(f())?;
224            }
225        }
226        Ok(())
227    }
228
229    // Internal helper to reallocate storage.
230    fn reallocate(&mut self, new_capacity: usize) -> Result<(), AllocError> {
231        assert!(new_capacity > 0);
232        assert!(new_capacity >= self.size);
233
234        if new_capacity > self.buf.len() {
235            Box::try_grow(&mut self.buf, new_capacity)?;
236        } else if new_capacity < self.buf.len() {
237            // SAFETY: We ensure in Vector that elements above `new_capacity`
238            // are uninitialized or already dropped.
239            unsafe {
240                Box::try_shrink(&mut self.buf, new_capacity)?;
241            }
242        }
243        Ok(())
244    }
245
246    // Internal helper to grow capacity if needed for a new element.
247
248    fn grow_for_new_element(&mut self) -> Result<(), AllocError> {
249        if self.size == self.buf.len() {
250            let new_capacity = if self.buf.len() == 0 {
251                CAPACITY_MINIMUM
252            } else {
253                self.buf.len() * CAPACITY_GROWTH_FACTOR
254            };
255            self.reallocate(new_capacity)?;
256        }
257        Ok(())
258    }
259
260    // Internal helper to shrink capacity if it's too large.
261    fn consider_shrinking(&mut self) {
262        if self.size * CAPACITY_SHRINK_FACTOR < self.buf.len() && self.buf.len() > CAPACITY_MINIMUM
263        {
264            let new_capacity = self.buf.len() / CAPACITY_SHRINK_FACTOR;
265            // If reallocation fails, we just keep the old capacity.
266            let _ = self.reallocate(new_capacity);
267        }
268    }
269
270    /// Creates a vector from an iterator.
271    /// Returns None if allocation fails.
272    ///
273    /// Creates a vector from an iterator with the given allocator.
274    pub fn try_from_iter_in<I: IntoIterator<Item = T>>(
275        iter: I,
276        allocator: A,
277    ) -> Result<Self, AllocError> {
278        let mut v = Vector::new_in(allocator);
279        let iter = iter.into_iter();
280
281        let (lower, _) = iter.size_hint();
282        if lower > 0 {
283            v.reserve(lower)?;
284        }
285
286        for item in iter {
287            v.push_back(item)?;
288        }
289        Ok(v)
290    }
291}
292
293impl<T, A: Allocator> Deref for Vector<T, A> {
294    type Target = [T];
295
296    fn deref(&self) -> &Self::Target {
297        // SAFETY: Vector maintains the invariant that elements from 0 to self.size are initialized.
298        unsafe { self.buf[0..self.size].assume_init_ref() }
299    }
300}
301
302impl<T, A: Allocator> DerefMut for Vector<T, A> {
303    fn deref_mut(&mut self) -> &mut Self::Target {
304        // SAFETY: Vector maintains the invariant that elements from 0 to self.size are initialized.
305        unsafe { self.buf[0..self.size].assume_init_mut() }
306    }
307}
308
309impl<T, A: Allocator> Drop for Vector<T, A> {
310    fn drop(&mut self) {
311        self.clear();
312    }
313}
314
315impl<T> Vector<T, DefaultAllocator> {
316    /// Creates an empty vector using the default allocator.
317    pub const fn new() -> Self {
318        Vector { buf: Box::empty_slice(), size: 0 }
319    }
320
321    /// Creates a vector from an iterator using the default allocator.
322    pub fn try_from_iter<I: IntoIterator<Item = T>>(iter: I) -> Result<Self, AllocError> {
323        let mut v = Vector::new();
324        let iter = iter.into_iter();
325
326        let (lower, _) = iter.size_hint();
327        if lower > 0 {
328            v.reserve(lower)?;
329        }
330
331        for item in iter {
332            v.push_back(item)?;
333        }
334        Ok(v)
335    }
336}
337
338impl<T> Default for Vector<T, DefaultAllocator> {
339    fn default() -> Self {
340        Self::new()
341    }
342}
343
344#[cfg(test)]
345mod tests {
346    extern crate std;
347
348    use super::*;
349
350    use core::cell::Cell;
351    use core::ptr::NonNull;
352
353    #[derive(Debug, PartialEq, Eq)]
354    struct TestState {
355        live_obj_count: Cell<usize>,
356        ctor_count: Cell<usize>,
357        dtor_count: Cell<usize>,
358        alloc_count: Cell<usize>,
359        fail_threshold: Cell<usize>,
360    }
361
362    impl Default for TestState {
363        fn default() -> Self {
364            Self {
365                live_obj_count: Cell::new(0),
366                ctor_count: Cell::new(0),
367                dtor_count: Cell::new(0),
368                alloc_count: Cell::new(0),
369                fail_threshold: Cell::new(usize::MAX),
370            }
371        }
372    }
373
374    #[derive(Clone)]
375    struct TestAllocator<'a> {
376        state: &'a TestState,
377    }
378
379    impl<'a> Allocator for TestAllocator<'a> {
380        fn allocate(&self, layout: core::alloc::Layout) -> Result<NonNull<[u8]>, AllocError> {
381            let current = self.state.alloc_count.get();
382            self.state.alloc_count.set(current + 1);
383            if current >= self.state.fail_threshold.get() {
384                return Err(AllocError);
385            }
386            DefaultAllocator::default().allocate(layout)
387        }
388
389        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: core::alloc::Layout) {
390            unsafe { DefaultAllocator::default().deallocate(ptr, layout) }
391        }
392
393        unsafe fn grow(
394            &self,
395            ptr: NonNull<u8>,
396            old_layout: core::alloc::Layout,
397            new_layout: core::alloc::Layout,
398        ) -> Result<NonNull<[u8]>, AllocError> {
399            let current = self.state.alloc_count.get();
400            self.state.alloc_count.set(current + 1);
401            if current >= self.state.fail_threshold.get() {
402                return Err(AllocError);
403            }
404            unsafe { DefaultAllocator::default().grow(ptr, old_layout, new_layout) }
405        }
406
407        unsafe fn shrink(
408            &self,
409            ptr: NonNull<u8>,
410            old_layout: core::alloc::Layout,
411            new_layout: core::alloc::Layout,
412        ) -> Result<NonNull<[u8]>, AllocError> {
413            let current = self.state.alloc_count.get();
414            self.state.alloc_count.set(current + 1);
415            if current >= self.state.fail_threshold.get() {
416                return Err(AllocError);
417            }
418            unsafe { DefaultAllocator::default().shrink(ptr, old_layout, new_layout) }
419        }
420
421        fn allocate_zeroed(
422            &self,
423            layout: core::alloc::Layout,
424        ) -> Result<NonNull<[u8]>, AllocError> {
425            let current = self.state.alloc_count.get();
426            self.state.alloc_count.set(current + 1);
427            if current >= self.state.fail_threshold.get() {
428                return Err(AllocError);
429            }
430            DefaultAllocator::default().allocate_zeroed(layout)
431        }
432    }
433
434    #[derive(Debug, Eq, PartialEq)]
435    struct TestObject<'a> {
436        val: usize,
437        alive: bool,
438        state: &'a TestState,
439    }
440
441    impl<'a> TestObject<'a> {
442        fn new(val: usize, state: &'a TestState) -> Self {
443            state.live_obj_count.set(state.live_obj_count.get() + 1);
444            state.ctor_count.set(state.ctor_count.get() + 1);
445            TestObject { val, alive: true, state }
446        }
447    }
448
449    impl<'a> Drop for TestObject<'a> {
450        fn drop(&mut self) {
451            if self.alive {
452                self.state.live_obj_count.set(self.state.live_obj_count.get() - 1);
453                self.state.dtor_count.set(self.state.dtor_count.get() + 1);
454            }
455        }
456    }
457
458    #[test]
459    fn test_empty() {
460        let v: Vector<u32> = Vector::new();
461        assert_eq!(v.len(), 0);
462        assert_eq!(v.capacity(), 0);
463        assert!(v.is_empty());
464    }
465
466    #[test]
467    fn test_push_pop() {
468        let mut v: Vector<u32> = Vector::new();
469        v.push_back(1).unwrap();
470        v.push_back(2).unwrap();
471        v.push_back(3).unwrap();
472
473        assert_eq!(v.len(), 3);
474        assert_eq!(v[0], 1);
475        assert_eq!(v[1], 2);
476        assert_eq!(v[2], 3);
477
478        assert_eq!(v.pop_back(), Some(3));
479        assert_eq!(v.pop_back(), Some(2));
480        assert_eq!(v.pop_back(), Some(1));
481        assert_eq!(v.pop_back(), None);
482    }
483
484    #[test]
485    fn test_insert_erase() {
486        let mut v: Vector<u32> = Vector::new();
487        v.push_back(1).unwrap();
488        v.push_back(3).unwrap();
489
490        v.insert(1, 2).unwrap();
491        assert_eq!(v.len(), 3);
492        assert_eq!(v[0], 1);
493        assert_eq!(v[1], 2);
494        assert_eq!(v[2], 3);
495
496        assert_eq!(v.erase(1), 2);
497        assert_eq!(v.len(), 2);
498        assert_eq!(v[0], 1);
499        assert_eq!(v[1], 3);
500    }
501
502    #[test]
503    fn test_resize() {
504        let mut v: Vector<u32> = Vector::new();
505        v.resize_with_default(5).unwrap();
506        assert_eq!(v.len(), 5);
507        for i in 0..5 {
508            assert_eq!(v[i], 0);
509        }
510
511        v.resize_with_default(2).unwrap();
512        assert_eq!(v.len(), 2);
513    }
514
515    #[test]
516    fn test_drop_behavior() {
517        let state = TestState::default();
518        {
519            let mut v: Vector<TestObject<'_>, TestAllocator<'_>> =
520                Vector::new_in(TestAllocator { state: &state });
521            v.push_back(TestObject::new(1, &state)).unwrap();
522            v.push_back(TestObject::new(2, &state)).unwrap();
523            assert_eq!(state.live_obj_count.get(), 2);
524        }
525        assert_eq!(state.live_obj_count.get(), 0);
526        assert_eq!(state.ctor_count.get(), 2);
527        assert_eq!(state.dtor_count.get(), 2);
528    }
529
530    #[test]
531    fn test_counting_allocator() {
532        let state = TestState::default();
533        {
534            let mut v: Vector<u32, TestAllocator<'_>> =
535                Vector::new_in(TestAllocator { state: &state });
536            v.push_back(1).unwrap(); // Causes allocation
537            assert_eq!(state.alloc_count.get(), 1);
538        }
539    }
540
541    #[test]
542    fn test_failing_allocator() {
543        let state = TestState::default();
544        state.fail_threshold.set(1); // Fail after 1st allocation
545
546        let mut v: Vector<u32, TestAllocator<'_>> = Vector::new_in(TestAllocator { state: &state });
547        v.push_back(1).unwrap(); // 1st alloc succeeds
548
549        // Fill up to capacity to trigger grow
550        for i in 2..=16 {
551            v.push_back(i).unwrap();
552        }
553        assert_eq!(v.len(), 16);
554        assert_eq!(v.capacity(), 16);
555
556        // Next push_back will try to grow and call alloc.
557        // Since threshold is 1, and we already did 1 alloc (at first push),
558        // next alloc will fail!
559        assert_eq!(v.push_back(17), Err(AllocError));
560        assert_eq!(v.len(), 16); // Size unchanged
561
562        // Verify elements are still valid
563        for i in 0..16 {
564            assert_eq!(v[i], (i + 1) as u32);
565        }
566    }
567
568    #[test]
569    fn test_truncate() {
570        let mut v: Vector<u32> = Vector::new();
571        v.push_back(1).unwrap();
572        v.push_back(2).unwrap();
573        v.push_back(3).unwrap();
574
575        v.truncate(2);
576        assert_eq!(v.len(), 2);
577        assert_eq!(v[0], 1);
578        assert_eq!(v[1], 2);
579
580        v.truncate(5); // No effect
581        assert_eq!(v.len(), 2);
582    }
583
584    #[test]
585    fn test_truncate_drops_elements() {
586        let state = TestState::default();
587        {
588            let mut v: Vector<TestObject<'_>, TestAllocator<'_>> =
589                Vector::new_in(TestAllocator { state: &state });
590            v.push_back(TestObject::new(1, &state)).unwrap();
591            v.push_back(TestObject::new(2, &state)).unwrap();
592            v.push_back(TestObject::new(3, &state)).unwrap();
593
594            assert_eq!(state.live_obj_count.get(), 3);
595
596            v.truncate(1);
597            assert_eq!(v.len(), 1);
598            assert_eq!(state.live_obj_count.get(), 1);
599            assert_eq!(state.dtor_count.get(), 2);
600        }
601        assert_eq!(state.live_obj_count.get(), 0);
602    }
603
604    #[test]
605    fn test_iterator() {
606        let mut v: Vector<u32> = Vector::new();
607        v.push_back(1).unwrap();
608        v.push_back(2).unwrap();
609
610        let mut it = v.iter();
611        assert_eq!(it.next(), Some(&1));
612        assert_eq!(it.next(), Some(&2));
613        assert_eq!(it.next(), None);
614
615        for x in v.iter_mut() {
616            *x += 10;
617        }
618
619        assert_eq!(v[0], 11);
620        assert_eq!(v[1], 12);
621    }
622
623    #[test]
624    fn test_box() {
625        let state = TestState::default();
626        {
627            let mut v: Vector<Box<TestObject<'_>, TestAllocator<'_>>, TestAllocator<'_>> =
628                Vector::new_in(TestAllocator { state: &state });
629            v.push_back(
630                Box::try_new_in(TestObject::new(1, &state), TestAllocator { state: &state })
631                    .unwrap(),
632            )
633            .unwrap();
634            assert_eq!(v.len(), 1);
635            assert_eq!(v[0].val, 1);
636        }
637    }
638
639    #[test]
640    fn test_try_from_iter() {
641        let items = [1, 2, 3, 4, 5];
642        let v: Vector<u32> = Vector::try_from_iter(items.iter().copied()).unwrap();
643        assert_eq!(v.len(), 5);
644        assert_eq!(v[0], 1);
645        assert_eq!(v[4], 5);
646    }
647
648    #[test]
649    fn test_try_from_iter_failing() {
650        let state = TestState::default();
651        state.fail_threshold.set(0); // Fail immediately
652
653        let items = [1, 2, 3, 4, 5];
654        let v: Result<Vector<u32, TestAllocator<'_>>, AllocError> =
655            Vector::try_from_iter_in(items.iter().copied(), TestAllocator { state: &state });
656        assert!(v.is_err());
657    }
658
659    #[test]
660    fn test_try_vec_macro() {
661        let v: Result<Vector<u32>, AllocError> = try_vec![1, 2, 3];
662        let v = v.unwrap();
663        assert_eq!(v.len(), 3);
664        assert_eq!(v[0], 1);
665        assert_eq!(v[2], 3);
666
667        let v2: Result<Vector<u32>, AllocError> = try_vec![0; 5];
668        let v2 = v2.unwrap();
669        assert_eq!(v2.len(), 5);
670        for i in 0..5 {
671            assert_eq!(v2[i], 0);
672        }
673    }
674
675    #[test]
676    fn test_try_vec_macro_failing() {
677        let state = TestState::default();
678        state.fail_threshold.set(0); // Fail immediately
679
680        let mut v: Vector<u32, TestAllocator<'_>> = Vector::new_in(TestAllocator { state: &state });
681        assert!(v.push_back(1).is_err());
682    }
683
684    #[test]
685    fn test_swap() {
686        let v1: Result<Vector<u32>, AllocError> = try_vec![1, 2, 3];
687        let mut v1 = v1.unwrap();
688        let v2: Result<Vector<u32>, AllocError> = try_vec![4, 5];
689        let mut v2 = v2.unwrap();
690
691        v1.swap(&mut v2);
692
693        assert_eq!(v1.len(), 2);
694        assert_eq!(v1[0], 4);
695        assert_eq!(v1[1], 5);
696
697        assert_eq!(v2.len(), 3);
698        assert_eq!(v2[0], 1);
699        assert_eq!(v2[1], 2);
700        assert_eq!(v2[2], 3);
701    }
702
703    #[test]
704    fn test_resize_with_value() {
705        let mut v: Vector<u32> = Vector::new();
706        v.resize(3, 42).unwrap();
707        assert_eq!(v.len(), 3);
708        assert_eq!(v[0], 42);
709        assert_eq!(v[1], 42);
710        assert_eq!(v[2], 42);
711
712        v.resize(1, 10).unwrap();
713        assert_eq!(v.len(), 1);
714        assert_eq!(v[0], 42); // Original element preserved
715    }
716
717    #[test]
718    fn test_resize_with() {
719        let mut v: Vector<u32> = Vector::new();
720        let mut c = 0;
721        v.resize_with(3, || {
722            c += 1;
723            c
724        })
725        .unwrap();
726        assert_eq!(v.len(), 3);
727        assert_eq!(v[0], 1);
728        assert_eq!(v[1], 2);
729        assert_eq!(v[2], 3);
730    }
731}