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
| Scenario | Recommended Type |
|---|---|
| Known size | super::ListBuilder - more efficient, no reallocation |
| Unknown size | ListAccumulator - bounded stack, dynamic growth |
| Streaming/iterators | ListAccumulator 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: usizeNumber of elements currently in the list.
cap: usizeCurrent capacity of the list.
scope: &'a ProtectScopeReference 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>
impl<'a> ListAccumulator<'a>
Sourcepub unsafe fn new(scope: &'a ProtectScope, initial_cap: usize) -> Self
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.
Sourcepub unsafe fn push_sexp(&mut self, sexp: SEXP)
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
sexpmust be a valid SEXP (it will be temporarily protected)
Sourcepub unsafe fn push_named<T: IntoR>(&mut self, name: &str, value: T)
pub unsafe fn push_named<T: IntoR>(&mut self, name: &str, value: T)
Sourcepub unsafe fn push_if_with<T: IntoR>(
&mut self,
condition: bool,
f: impl FnOnce() -> T,
)
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.