7 ms·
> append-only-vec > This is a pretty simple type, which is a vector that you can push into, but cannot modify the elements of. The data structure never moves a
by waterTanuki 1mo ago
> append-only-vec
> This is a pretty simple type, which is a vector that you can push into, but cannot modify the elements of. The data structure never moves an element once allocated, so you can push to the vec even while holding references to elements that have already been pushed.
This is the left-pad of rust. Reconsider your life decisions if you need to pull in an external dependency replicable with 30 lines of code:
use std::vec::Vec;
#[derive(Debug)]
pub struct AppendOnlyVec<T> {
inner: Vec<T>,
}
impl<T> AppendOnlyVec<T> {
pub fn new() -> Self {
Self {
inner: vec![],
}
}
pub fn push(&mut self, element: T) {
self.inner.push(element);
}
pub fn clear(&mut self) {
self.inner.clear();
}
}
- speedstyle 1mo ago> The data structure never moves an element once allocated Yours will reallocate every so often, invalidating element references. append_only_vec requires only `&self` to push, and can also be used concurrently. Adding these abilities requires unsafe, so it wants its own module to uphold invariants on private members. Add an efficient well-tested impl and several other traits you might want, and a shared crate is entirely reasonable.
- waterTanuki 1mo ago> Yours will reallocate every so often, invalidating element references. append_only_vec requires only &self to push, Then the crate is lying about its intentions or performing black magic using RefCell under the hood to go behind the user's back. A vec is a vec. If I don't want re-allocations I will use .with_capacity() and cap it or use a plain array. Also the data has to be changed somewhere to happen, and I'd rather the API be honest and give me &mut self than lie and say &self.
- speedstyle 1mo agoThe point of the crate, the readme you quoted, is > you can push to the vec even while holding references to elements that have already been pushed. Expressing this in Rust (without leaking references to a dropped container) means taking &self. It's true that the container struct itself (chunk pointers, len) is mutated, but the compiler has no distinction between this and the pointee data, so you use ..Cell. It does allocate, there's no capacity limit, but it guarantees stable pointers to existing items.
- delifue 1mo agoIt's not like leftpad. It uses segmented array and interally does synchronization, not a simple wrapper to Vec. The append only takes immutable borrow. Its capability cannot be replaced by RefCell because RefCell doesn't allow appending while keeping borrow.