-
Notifications
You must be signed in to change notification settings - Fork 432
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
New error handling + type #225
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! I had some minor comments.
I see you basically copied the entire os.rs
file, and created a new error
module. Nice.
src/impls.rs
Outdated
@@ -167,4 +167,40 @@ pub fn next_u64_via_fill<R: Rng+?Sized>(rng: &mut R) -> u64 { | |||
impl_uint_from_fill!(rng, u64, 8) | |||
} | |||
|
|||
/// Implement `fill_bytes` via `try_fill` with implicit error handling. | |||
pub fn fill_via_try_fill<R: Rng+?Sized>(rng: &mut R, dest: &mut [u8]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still feel a bit uneasy about this function. We had to pick some defaults for how many times to retry or how long to wait in case of an error, that may not suite every RNG.
What do you think about moving it to os.rs
and not making it public?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the moment it's not public. I see your point though, we could simply force every use-case to have its own custom implementation instead of having this one. I'm not sure.
/// [`fill_bytes`]: trait.Rng.html#method.fill_bytes | ||
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { | ||
Ok(self.fill_bytes(dest)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just as a test I removed the default implementation, and you did not miss to implement it for any wrappers etc. 👍.
I would like to see the default implementations be removed, but good to wait until all the changes for RNG implementations are merged.
#[inline] | ||
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { | ||
(**self).try_fill_bytes(dest) | ||
} | ||
} | ||
|
||
#[cfg(feature="std")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not part of this PR, but should this also be available with the alloc
feature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With that I mean impl<R: ?Sized> Rng for Box<R> where R: Rng {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah. Probably. Make a separate PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. But I should probably wait until this PR has landed because they will conflict?
src/os.rs
Outdated
} | ||
fn next_u32(&mut self) -> u32 { | ||
// note: `next_u32_via_fill` does a byte-swap on big-endian | ||
// architectures, which is not really needed here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it was me who wrote this comment? I don't really think it matters, the system call and OS RNG should dwarf the time the byte swap takes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it was me. But yes, I don't think it's important, so the comment could be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On that topic, impl_uint_from_fill
does not call .to_le()
. It should, surely?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
He, your right! While the documentations says it uses little-endian order. Really need some tests there 😄. Edit: someday though
@@ -46,34 +47,24 @@ impl<R: Read> ReadRng<R> { | |||
|
|||
impl<R: Read> Rng for ReadRng<R> { | |||
fn next_u32(&mut self) -> u32 { | |||
// This is designed for speed: reading a LE integer on a LE | |||
// platform just involves blitting the bytes into the memory | |||
// of the u32, similarly for BE on BE; avoiding byteswapping. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably a breaking change on big-endian? I don't think this will be a problem for anyone, but maybe good to mention.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but only because it wasn't portable before. I doubt anyone was depending on the old non-portable behaviour.
src/os.rs
Outdated
panic!("kern.arandom sysctl failed! (returned {}, s.len() {}, oldlenp {})", | ||
ret, s.len(), s_len); | ||
// Old format string: | ||
// "kern.arandom sysctl failed! (returned {}, s.len() {}, oldlenp {})" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we care about this?
I think I would go with renaming. For RNG implementations we are going to have breaking changes anyway, so no problem in renaming there. For users of Related thought: it would be great if we had some function that could fill slices of any type. Like the |
I think I agree about the renaming Not sure what you mean about filling slices? Travis points out something about Rustc 1.15, though very easy to work around:
|
src/lib.rs
Outdated
/// Fill `dest` entirely with random data. | ||
/// | ||
/// Implementations of this trait must implement at least one of | ||
/// `next_u32`, `next_u64`, `fill` and `try_fill` directly. In the case this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is true, only next_u32
has to be implemented? But this part of the documentation is not going to live long anyway.
src/lib.rs
Outdated
/// This is the only method which allows an RNG to report errors while | ||
/// generating random data; other methods either handle the error | ||
/// internally or panic. This method is intended to allow error-handling | ||
/// when seeding keys or PRNGs from external (true) RNGs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for being picky... "This method is intended to" sounds a bit specific. Maybe "This method can be used to"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is specific, and intended to explain why there isn't try_next_u64
etc. You think it's over-specific? I mean it's obvious there may be other ways to use it, but this is the only important one I see.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is a good intention, useful to add. Could you reword it a little, because I missed it?
Something like
This method is intended to be the way to use external (true) RNGs, like
OsRng
. You primarily want to use it to seed keys or (infallible) PRNGs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, done. I'll rebase later, to let you review changes now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure what there is left to rebase or review?
It was just a thought. Can we provide a function that can fill slices of any size, not just arrays of at most 32 elements as I have something working, but not very ergonomic: https://gist.github.com/pitdicker/ba4c08bf407c04a6f2a63a8116afd4d1 Don't let it hold up this PR though. |
Interesting idea. Nothing to do with this PR though as I see it. |
Having a method that can fill slices of multiple types could be an argument to rename But I like the rename here and think it is the right choice. I will not distract this PR further. |
Sorry, I see what you mean now: replace I don't know. The reason we switched key types to byte arrays was to avoid Endianness issues. I guess we could even go back to |
I am really all for keeping the I think a more generic method can be useful for And the only overhead for integer slices of having the |
A generic Of course, you can't generated an unsized type like a slice directly, so maybe |
Rebased, but I think I'll remove the last two renaming commits; now I've re-read the comments I see @burdges had the same idea back in October. It also avoids unnecessary breakage. |
We can still have |
To some extent, yes, because the way most people handle errors is not much better than BTW I revised that handling as you suggested (see last commit). |
I hope users of Then the only open thing left is the endianness in |
I have a TODO note on the Endianness. It wasn't introduced in this PR so I won't fix here. Since we deliberately report |
Feel free to merge (from me) when you think it is the right time. |
This removes support for the NaCl target, which appears to be dead.
This brings in the new error type and handling from dhardy/master. See dhardy#10.
It also adds
try_fill_bytes
; see dhardy#12 and dhardy#27. (There's still a question on naming here.)fill_via_try_fill
includes some code for implicit error handling; see dhardy#25.Finally, support for NaCl is removed from
OsRng
; see dhardy#19.Note that for now all
Rng
methods besidesnext_u32
have default implementations; this may change before 0.5 but not in this PR.Also note that the new
error
module is deliberately private; probably it will move torand-core
, however the names publically exported inrand
will still be exported there.