Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infallible Vec operations #341

Open
robin-nitrokey opened this issue Jan 30, 2023 · 4 comments
Open

Infallible Vec operations #341

robin-nitrokey opened this issue Jan 30, 2023 · 4 comments

Comments

@robin-nitrokey
Copy link

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 a Vec from an array with the same capacity (would also be useful for constants)
  • fill(&mut self, value: T): resize to capacity and clone value to empty slots
  • fill_default(&mut self): resize to capacity and write T::default() to empty slots
  • replace(&mut self, other: &Self): clear this Vec and copy the data from other
@reitermarkus
Copy link
Member

from_array is now implemented in #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?

@robin-nitrokey
Copy link
Author

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.

@reitermarkus
Copy link
Member

@robin-nitrokey, can you give a full example on how fill would be used?

Maybe v.extend(core::iter::repeat(...)) works?

@robin-nitrokey
Copy link
Author

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()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants