Skip to main content

ListAccumulator

Struct ListAccumulator 

Source
pub struct ListAccumulator<'a> {
    list: ReprotectSlot<'a>,
    temp: ReprotectSlot<'a>,
    len: usize,
    cap: usize,
    scope: &'a ProtectScope,
    names: Vec<Option<String>>,
}
Expand description

Accumulator for building lists when the length is unknown upfront.

Unlike super::ListBuilder which requires knowing the size at construction, ListAccumulator supports dynamic growth via push. It uses ReprotectSlot internally to maintain O(1) protect stack usage regardless of how many elements are pushed.

§When to Use

ScenarioRecommended Type
Known sizesuper::ListBuilder - more efficient, no reallocation
Unknown sizeListAccumulator - bounded stack, dynamic growth
Streaming/iteratorsListAccumulator or collect_list

§Growth Strategy

The internal list grows exponentially (2x) when capacity is exceeded, achieving amortized O(1) push. Elements are copied during growth.

§Example

unsafe fn collect_filtered(items: &[i32]) -> SEXP {
    let scope = ProtectScope::new();
    let mut acc = ListAccumulator::new(&scope, 4); // initial capacity hint

    for &item in items {
        if item > 0 {
            acc.push(item);  // auto-converts via IntoR
        }
    }

    acc.into_root().get()
}

Fields§

§list: ReprotectSlot<'a>

The current list container (protected via ReprotectSlot).

§temp: ReprotectSlot<'a>

Temporary slot for element conversion and list growth.

§len: usize

Number of elements currently in the list.

§cap: usize

Current capacity of the list.

§scope: &'a ProtectScope

Reference to the scope for creating the final Root.

§names: Vec<Option<String>>

Per-element names (None = unnamed, Some = named).

Implementations§

Source§

impl<'a> ListAccumulator<'a>

Source

pub unsafe fn new(scope: &'a ProtectScope, initial_cap: usize) -> Self

Create a new accumulator with the given initial capacity.

A capacity of 0 is valid; the list will grow on first push.

§Safety

Must be called from the R main thread.

Source

pub unsafe fn push<T: IntoR>(&mut self, value: T)

Push a value onto the accumulator.

The value is converted to a SEXP via IntoR and inserted. If the internal list is full, it grows automatically.

§Safety

Must be called from the R main thread.

Source

pub unsafe fn push_sexp(&mut self, sexp: SEXP)

Push a raw SEXP onto the accumulator.

§Safety
  • Must be called from the R main thread
  • sexp must be a valid SEXP (it will be temporarily protected)
Source

pub unsafe fn push_named<T: IntoR>(&mut self, name: &str, value: T)

Push a named value onto the accumulator.

§Safety

Must be called from the R main thread.

Source

pub unsafe fn push_if<T: IntoR>(&mut self, condition: bool, value: T)

Push a value only if the condition is true.

§Safety

Must be called from the R main thread.

Source

pub unsafe fn push_if_with<T: IntoR>( &mut self, condition: bool, f: impl FnOnce() -> T, )

Push a lazily-evaluated value only if the condition is true.

The closure is only called if condition is true.

§Safety

Must be called from the R main thread.

Source

pub unsafe fn extend_from<I, T>(&mut self, iter: I)
where I: IntoIterator<Item = T>, T: IntoR,

Push all items from an iterator.

§Safety

Must be called from the R main thread.

Source

unsafe fn grow(&mut self)

Grow the internal list by 2x.

§Safety

Must be called from the R main thread.

Source

pub fn len(&self) -> usize

Get the current number of elements.

Source

pub fn is_empty(&self) -> bool

Check if the accumulator is empty.

Source

pub fn capacity(&self) -> usize

Get the current capacity.

Source

pub unsafe fn into_root(self) -> Root<'a>

Finalize the accumulator and return a Root pointing to the list.

The returned list is truncated to the actual length (if smaller than capacity).

§Safety

Must be called from the R main thread.

Source

pub unsafe fn into_sexp(self) -> SEXP

Finalize and return the raw SEXP.

§Safety

Must be called from the R main thread.

Auto Trait Implementations§

§

impl<'a> !Freeze for ListAccumulator<'a>

§

impl<'a> !RefUnwindSafe for ListAccumulator<'a>

§

impl<'a> !Send for ListAccumulator<'a>

§

impl<'a> !Sync for ListAccumulator<'a>

§

impl<'a> Unpin for ListAccumulator<'a>

§

impl<'a> UnsafeUnpin for ListAccumulator<'a>

§

impl<'a> !UnwindSafe for ListAccumulator<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.