-
Notifications
You must be signed in to change notification settings - Fork 182
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
Add function which returns random array? #281
Comments
Personally, I don't think adding the API is worth dealing with a v0.3 or some sort of conditional compilation. This seems like the type of thing best left to I think it would b e better to just change the rand_core implementation to be: impl RngCore for OsRng {
fn next_u32(&mut self) -> u32 {
let mut u = mem::MaybeUninit::uninit();
unsafe { getrandom_raw(u.as_mut_ptr().cast(), mem::size_of::<u32>()) }.unwrap();
u.assume_init()
}
fn next_u64(&mut self) -> u64 {
let mut u = mem::MaybeUninit::uninit();
unsafe { getrandom_raw(u.as_mut_ptr().cast(), mem::size_of::<u64>()) }.unwrap();
u.assume_init()
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
self.try_fill_bytes(dest).unwrap()
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
Ok(getrandom(dest)?)
}
} Then if |
I think the methods could be useful for users which depend directly on I agree that probably it's not worth to release together with |
I think it is a very useful feature.
I disagree. I'd rather not need to depend on
Rust 1.51.1 was released over 1.5 years ago (March 2021). I support increasing the MSRV to 1.51 to get this functionality. |
This is exactly what rust-lang/rust#80149 would best use.
I'm not really sure that these are justified to add. |
I looked more deeply into some applications that would use these and I found that having functions that return |
I support adding such an API. My goal for advocating for such functionality is to eliminate all uses of Consider this basic function, which I think is the one most agreeable to the most people: #[inline(always)]
pub fn getrandm_array<const N: usize>() -> Result<[u8; N], Error> {
let mut uninit: MaybeUninit<[u8; N]> = MaybeUninit::uninit();
// TODO: `uninit.as_bytes_mut()` when that is available.
{
// SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
let as_bytes_mut = unsafe {
core::slice::from_raw_parts_mut(uninit.as_mut_ptr() as *mut MaybeUninit<u8>, N)
};
getrandom::getrandom_uninit(as_bytes_mut)?;
}
// SAFETY: `dest` has been fully initialized by `imp::getrandom_inner`
// since it returned `Ok`.
Ok(unsafe { uninit.assume_init() })
} I found that such a function was useful for applications that operate on byte arrays, e.g. HMAC keys, AES keys, TLS ClientHello/ServerHello However, for other applications, I found the function way too limiting because Rust doesn't have an API equivalent to #[inline(always)]
pub fn getrandm_arrays<const M: usize, const N: usize>() -> Result<[[u8; N]; M], Error> {
let mut uninit: MaybeUninit<[[u8; N]; M]> = MaybeUninit::uninit();
// TODO: `uninit.as_bytes_mut()` when that is available.
{
// SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
let as_bytes_mut = unsafe {
core::slice::from_raw_parts_mut(uninit.as_mut_ptr() as *mut MaybeUninit<u8>,
core::mem::size_of::<[[u8; N]; M]>()
)
};
getrandom::getrandom_uninit(as_bytes_mut)?;
}
// SAFETY: `dest` has been fully initialized by `imp::getrandom_inner`
// since it returned `Ok`.
Ok(unsafe { uninit.assume_init() })
} The the above two functions, I can efficiently implement everything I need, in a pretty type-safe way, without using Notice in particular that the compiler should verify that I've also considered doing more elaborate support for types that are "plain old data" or more generally which are safe to transmute from an array of arbitrary bytes of the same length: pub unsafe trait Pod {}
unsafe impl Pod for u64 {}
unsafe impl Pod for Wrapping<u64> {}
unsafe impl Pod for u8 {}
unsafe impl<T: Pod, const N: usize> Pod for [T; N] {}
/// ...
#[inline(always)]
pub fn getrandm_array_pod<T: Pod, const N: usize>() -> Result<[T; N], Error> {
let mut uninit: MaybeUninit<[T; N]> = MaybeUninit::uninit();
// TODO: `uninit.as_bytes_mut()` when that is available.
{
// SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
let as_bytes_mut = unsafe {
core::slice::from_raw_parts_mut(uninit.as_mut_ptr() as *mut MaybeUninit<u8>,
core::mem::size_of::<[T; N]>()
)
};
getrandom::getrandom_uninit(as_bytes_mut)?;
}
// SAFETY: `dest` has been fully initialized by `imp::getrandom_inner`
// since it returned `Ok`.
Ok(unsafe { uninit.assume_init() })
} However, I found that at least Nightly Rustc didn't optimize uses of such a function any better than the equivalent that uses Therefore, I propose we implement (only) As far as MSRV goes, I persoally would prefer to set the MSRV to 1.51. However, if that's too drastic, I suggest we add a |
Also, I found that |
I copied those comments from |
Draft PR #293 builds on PR #291 to add a single |
Now I've reconsidered my comments above. I think that having generic functions like this in |
@briansmith sounds good! And I agree, future integration or compatibility with |
getrandom
is often used to generate seed for user-space PRNG. #279 adds unsafe raw API which allows to remove redundant initialization of buffers. So I wonder if it could be worth to introduce the following safe wrappers:Of course,
getrandom_array
implies MSRV bump to 1.51, which could be done in sync withrand v0.9
.The text was updated successfully, but these errors were encountered: