A data structure to allow building a [T; N] dynamically. Safely handling drops and efficiently being convertable into the underlying [T; N].
Motivation
Array initialisation is surprisingly unsafe. The safest way is to initialise with a default value, then replacing the values. This is not always possible and requires moving to using MaybeUninit and unsafe. This is very easy to get wrong.
For example:
let mut array: = uninit_array;
array.write;
panic!;
Despite being completely safe, this will cause a memory leak. This is because MaybeUninit does not call drop for the string.
Guide-level explanation
Definition
This RFC proposes a new struct, ArrayBuilder. It has a very basic API designed solely for building new [T; N] types without initialising it all before hand.
This is not a heapless replacement for Vec.
// ArrayBuilder implements drop safely, and prevents any memory leaks
// Implements AsRef/AsMut for slices. These will return references to
// any initialised data. Useful if extracting data when the ArrayBuilder is not yet full
Example uses
A very simple demonstration:
let mut arr = new;
arr.push;
arr.push;
arr.push;
arr.push;
let arr: = arr.build.unwrap;
If you want the first 10 square numbers in an array:
let mut arr = new;
for i in 1..=10
arr.build.unwrap
A simple iterator that can iterate over blocks of N:
Reference-level explanation
A pretty clear example could be porting relevant features from arrayvec::ArrayVec.
Example basic implementation (does not cover the entire API suggested):
Drawbacks
As suggested above. There already exists several crates that can implement this functionality. arrayvec has over 20 million downloads and is moving to version 1.0 soon.
Rationale and alternatives
Many of the other implementations are focused on this pattern being for 'heapless' Vec.
This is a reasonable desire, especially in no_std use cases and low memory embedded
systems. This is not the case for this proposal. Instead specifically related to initiating
arrays dynamically then building them into full arrays.
Another reason to have this in core, is that there are already some PRs for adding new features
to core::array. For example, from_fn or FromIterator. It would be nice to have a re-usable, safe backing for them. And then it might as well be stablised and exposed to others too.
Prior art
array-init crate:
This is good for basic tasks, but it has only a very minimal API. It only allows for creating an array in one big go. There's no way to extract the data out of a partial fill.
arrayvec crate:
Discussed above, this crate focuses on the heapless Vec aspect. It can be used to implement
array initialisation, but that doesn't seem to be it's primary intention.
ArrayVec/StackVec RFC:
Simply put, this appears to be a re-implementation of arrayvec::ArrayVec in core.
Unresolved questions
- What should the exact API be?
Future possibilities
Once implemented in core, some current implementations and PRs could be updated to use it.