BulkVecExtender

Trait BulkVecExtender 

Source
pub trait BulkVecExtender<T> {
    // Required method
    fn bulk_extend_guard(
        &mut self,
        elements_to_write: usize,
    ) -> BulkExtendGuard<'_, T>;
}
Expand description

BulkVecExtender is a simple utility trait that allows you to bulk extend a Vec and return a &mut [T] slice that you can write to - much faster than individual push() calls, which has to check for both bounds and capacity.

§Example

Instead of using push() in a hot loop (which is expensive due to bounds checks):

// Slow: each push() does bounds checking
let mut vec = Vec::new();
for value in some_data {
    if condition(value) {
        vec.push(value);  // Bounds check on every call!
    }
}

Use bulk_extend_guard() to get a RAII guard and write directly:

let mut vec = Vec::new();
let max_elements = 100;

{
    // Get a guard to write to (no bounds checks during writes!)
    let mut guard = vec.bulk_extend_guard(max_elements);

    // Write directly to the guard - much faster than push()
    let mut written = 0;
    for value in some_data.iter().take(max_elements) {
        if condition(*value) {
            guard[written] = *value;
            written += 1;
        }
    }

    // Set actual number of elements written (only needed for partial writes)
    guard.set_written(written);
    // guard drops here, vec is automatically truncated to correct length
}

§Performance

This trait is designed to eliminate the overhead of Vec::push() in hot loops:

  • No bounds checking during writes (you get a pre-allocated slice)
  • Bulk allocation happens once, not per-element
  • Better for SIMD - you can write entire SIMD vectors at once
  • Cache-friendly - sequential writes to a pre-allocated buffer

Benchmarks show Vec::push() can cost 35% of total performance in hot loops, even with pre-allocation. This trait eliminates that overhead.

Required Methods§

Source

fn bulk_extend_guard( &mut self, elements_to_write: usize, ) -> BulkExtendGuard<'_, T>

Returns a RAII guard that extends the Vec and automatically finalizes on drop.

This is the preferred method for most use cases as it avoids borrow checker issues and automatically handles finalization.

By default, assumes all elements will be written. If you write fewer elements, call guard.set_written(count) before the guard drops.

§Example
let mut vec: Vec<u8> = Vec::new();
{
    let mut guard = vec.bulk_extend_guard(10);
    for i in 0..10 {
        guard[i] = i as u8;
    }
    // guard drops here, vec length is automatically set to 10
}
assert_eq!(vec.len(), 10);
§Example with partial writes
let mut vec: Vec<u8> = Vec::new();
{
    let mut guard = vec.bulk_extend_guard(100);
    guard[0] = 42;
    guard[1] = 43;
    guard.set_written(2);  // only wrote 2 elements
}
assert_eq!(vec.len(), 2);

Implementations on Foreign Types§

Source§

impl<T> BulkVecExtender<T> for Vec<T>

Source§

fn bulk_extend_guard( &mut self, elements_to_write: usize, ) -> BulkExtendGuard<'_, T>

Implementors§