Skip to main content

luaur_common/methods/
small_vector_grow.rs

1use crate::macros::luau_assert::LUAU_ASSERT;
2use crate::records::small_vector::SmallVector;
3
4pub fn small_vector_grow<T, const N: usize>(sv: &mut SmallVector<T, N>, new_size: u32) {
5    let mut new_size = new_size;
6
7    let max = sv.capacity();
8    let proposed = max + (max >> 1);
9
10    if proposed > new_size {
11        new_size = proposed;
12    } else {
13        new_size += 4;
14    }
15
16    LUAU_ASSERT!(new_size < 0x40000000);
17
18    unsafe {
19        // Allocate uninitialized memory for new elements.
20        let layout = core::alloc::Layout::array::<T>(new_size as usize).expect("invalid layout");
21        let raw = alloc::alloc::alloc(layout) as *mut T;
22        let new_data = raw;
23
24        let count = sv.size() as usize;
25        let ptr = sv.as_mut_slice().as_mut_ptr();
26
27        // Move-construct elements into the new allocation.
28        core::ptr::copy_nonoverlapping(ptr, new_data, count);
29
30        // Drop old elements.
31        for i in 0..count {
32            core::ptr::drop_in_place(ptr.add(i));
33        }
34
35        // If the old storage was heap-backed, free it.
36        if sv.capacity() != N as u32 {
37            let old_layout = core::alloc::Layout::array::<T>(max as usize).expect("invalid layout");
38            alloc::alloc::dealloc(sv.as_mut_slice().as_mut_ptr() as *mut u8, old_layout);
39        }
40
41        // Update metadata using existing API behavior.
42        sv.reserve(new_size);
43        let _ = new_data;
44    }
45}
46
47extern crate alloc;