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

API Changes #439

Closed
josephlr opened this issue May 29, 2024 · 6 comments
Closed

API Changes #439

josephlr opened this issue May 29, 2024 · 6 comments
Milestone

Comments

@josephlr
Copy link
Member

Splitting off from #433 to discuss any breaking API changes we might want to make to the crate. CC @briansmith @newpavlov @dhardy @vks Let me know what you think or if I missed anything.

My proposed new API for this crate would be to introduce a getrandom::Opts structure which would initially be empty, but could have fields added over time to support things like #365. This would allow us to introduce new functionality by just adding new fields to Opts . Specifically, the API would be:

#[non_exhaustive] // Possible now that MSRV >= 1.40
#[derive(Clone, Copy, Debug, Default)]
pub struct Opts {}

impl Opts {
    pub const fn new() -> Self;
}

pub fn fill(buf: &mut [u8], opts: Opts) -> Result<(), Error>;
/// Do we even want this? See discussion below
pub fn fill_uninit(buf: &mut [MaybeUninit<u8>], opts: Opts) -> Result<&mut [u8], Error>;

/// Convenience wrapper for `fill(buf, Opts::new())`
/// I don't think we would want to deprecate this.
pub fn getrandom(buf: &mut [u8]) -> Result<(), Error>;

Changes to the Error type

I think we should mostly leave the API as-is. I think it's perfectly fine to expose all error constants on all targets. Given that the error codes aren't exhaustive, exposing all the constants doesn't do any harm, and makes some handing code easier to write.

I do think that we should get rid of the From<NonZeroU32> impl, as we really only use that conversion internally. It also might be nice to add an Error::from_raw_os_error method to mirror raw_os_error(), but this isn't a breaking change.

Is it worth keeping the uninit methods?

Given that getrandom_uninit is rarely used, I think it's fine to just replace it with fill_uninit. But this brings up a more important question, does it even make sense to keep the uninit methods at all? They add complexity and unsafe code, but it's unclear if they are worth it. We have benchmarks which compare calling getrandom_uninit vs zeroing a buffer and calling getrandom. Even with very fast (> 100 MB/sec) rng sources, the uninit methods aren't consistently faster (and any difference is within the margin of error).

On Linux (cargo bench --jobs=1):

test aes128::bench_getrandom        ... bench:         409 ns/iter (+/- 20) = 39 MB/s
test aes128::bench_getrandom_uninit ... bench:         413 ns/iter (+/- 37) = 38 MB/s
test p256::bench_getrandom          ... bench:         421 ns/iter (+/- 19) = 76 MB/s
test p256::bench_getrandom_uninit   ... bench:         416 ns/iter (+/- 23) = 76 MB/s
test p384::bench_getrandom          ... bench:         527 ns/iter (+/- 126) = 91 MB/s
test p384::bench_getrandom_uninit   ... bench:         543 ns/iter (+/- 169) = 88 MB/s
test page::bench_getrandom          ... bench:       8,676 ns/iter (+/- 219) = 472 MB/s
test page::bench_getrandom_uninit   ... bench:       8,591 ns/iter (+/- 551) = 476 MB/s

I would be fine removing the uninit methods entirely, as it would simplify our implementation in multiple places.

Handling register_custom_getrandom!()

I would propose having the register_custom_getrandom! support both functions with the type of fill and those with the type of fill_uninit (if we keep the uninit methods). We can use traits/generics to have the macro work with either function type. Similar to the current implementation, the macro would generate a #[no_mangle] extern "Rust" function, but it would have a different signature:

#[no_mangle]
unsafe fn __getrandom_fill(dest: *mut u8, len: usize, opts: *const Opts) -> u32;

I would also propose having the macro also create an unsafe fn __getrandom_custom(dest: *mut u8, len: usize) function, allowing the custom implementation registered with the next version of getrandom to still work with getrandom 0.2 without folks having to do tricks like those suggested in #433 (comment)

@briansmith
Copy link
Contributor

I think we should close this issue in favor of the existing issues for each of these topics.

@josephlr josephlr added this to the Next Release milestone May 29, 2024
@dhardy
Copy link
Member

dhardy commented Jun 4, 2024

I echo @briansmith's point: this is a number of unrelated issues.

get rid of the From<NonZeroU32> impl

The only use-case I can think of is if error codes need to be pushed through some other API (FFI) then converted back into an Error. Possibly it should be kept simply as the inverse of fn Error::code, though I also don't know how useful that is.

uninit

I've had people ask for this functionality several times in rand, yet I agree with your sentiment that it's essentially a useless optimisation.

@briansmith
Copy link
Contributor

I filed #455 about deprecating/removing The From<NonZeroU32> implementation and #454 about deprecating/removing getrandom_uninit.

@dhardy
Copy link
Member

dhardy commented Jun 4, 2024

Remaining items in this issue are:

My proposed new API for this crate would be to introduce a getrandom::Opts structure which would initially be empty, but could have fields added over time to support things like #365. This would allow us to introduce new functionality by just adding new fields to Opts .

The only motivation given is for a non-blocking API, which as noted in #365 would ideally want a different function signature, hence it makes more sense to use a separate function.

Is there any other motivation? I do not think we should add Opts "just in case".

@briansmith
Copy link
Contributor

It would be better to just discuss non-blocking getrandom in #365 and/or if we need a discussion regarding how to add options to the API, we should do that in its own issue. There are non-obvious considerations in the design of the options API.

@josephlr
Copy link
Member Author

josephlr commented Jun 4, 2024

Good point @briansmith I've copied relevant sections from this issue into #454 #365 #455

@josephlr josephlr closed this as completed Jun 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants