Infallible Vec operations
Some operations on a Vec<T, N> are infallible but can only be implemented using fallible methods. What do you think about adding more infallible methods? For example:
from_array(data: [T; N]): construct aVecfrom an array with the same capacity (would also be useful for constants)fill(&mut self, value: T): resize to capacity and clonevalueto empty slotsfill_default(&mut self): resize to capacity and writeT::default()to empty slotsreplace(&mut self, other: &Self): clear thisVecand copy the data fromother
from_array is now implemented in https://github.com/rust-embedded/heapless/pull/352.
fill already exists on slice, i.e. via DerefMut, same with fill_with(Default::default) instead of fill_default. These only fill up to the current length, though. What is the use case for the fill methods filling up to capacity? Is it covered now with .spare_capacity_mut().fill(…)?
For replace, I assume this should work only for Vec with the same capacity, otherwise it would still need to be fallible. Again, what is the use case for this method?
Good to see from_array being added! Unfortunately, the implementation is not const. It would still be useful to be able to create non-empty constants.
My use case for fill is preparing a buffer for functions that expect a &mut [u8] for writing. Currently, you have to call v.resize_default(v.capacity()) which is fallible. spare_capacity_mut().fill(MaybeUninit::new(...)) should work but is not really intuitive.
For replace, I don’t remember the specific use case. I’ll report back if I find it again.
@robin-nitrokey, can you give a full example on how fill would be used?
Maybe v.extend(core::iter::repeat(...)) works?
I don’t think extend + repeat would work as extend “[p]anics if the vec cannot hold all elements of the iterator.”
Here is a real world example:
https://github.com/trussed-dev/ctap-types/blob/084db87a800e1204bcfdc3e25ca46bc4a81650ba/src/ctap2.rs#L148-L175
serialize receives a &mut Vec<u8, N> buffer and wants to write data to the buffer by calling cbor_serialize, which expects a &mut [u8] buffer. So we need to extend the Vec to capacity, write to it and then truncate it to the written data.
Here, buffer.resize_default(buffer.capacity()).ok() could be replaced with one of:
buffer.fill(Default::default())buffer.fill_default()buffer.resize_to_capacity()