Error handling#7
Conversation
3fa27ca to
a43a3f7
Compare
|
I am slowly getting better at rebasing 😄 |
| pub struct Error; | ||
|
|
||
| #[cfg(feature="std")] | ||
| impl From<::std::io::Error> for Error { |
There was a problem hiding this comment.
I did not add this From implementation yet.
I actually had one, that would map the IO errors you could get for OsRng to the appropriate RngError.
But I am not sure it would always be correct for other RNGs implementations. It are the more exotic ones that produce errors...
Not adding one forces RNG implementations to put a little more thought into their error handling. Which might be a plus... For ReadRng the missing implementation did not really make it more difficult, and I also expect it not to for OsRng.
| } | ||
|
|
||
| fn try_fill(&mut self, dest: &mut [u8]) -> Result<()> { | ||
| impls::try_fill_via_u32(self, dest) |
| } | ||
| /// Error type for random number generators. | ||
| #[derive(Copy, PartialEq, Eq, Clone, Debug)] | ||
| pub enum RngError { |
There was a problem hiding this comment.
I'd prefer the name Error personally — less repetition and matches usual naming conventions.
There was a problem hiding this comment.
I thought I was following some sort of convention after reading the Error Handling Chapter in TRPL again. But Error seems to be common, and it shorter. I will change it.
Also just noticed: It should implement the ::std::error::Error trait.
| } | ||
|
|
||
| /// Result type (convenience type-def) | ||
| pub type Result<T> = ::std::result::Result<T, Error>; |
There was a problem hiding this comment.
Have you seen my reason in the PR description?
In part the reason is that I was bitten by the redefined Result type ;-).
But I don't really see a reason to have it, as we only use it in the trait definitions in a handful of places.
In a library that uses the std::result::Result, would users also import rand::Result? Or would they want to use the std one and import our rand::Error?
It seems to me (but I am inexperienced) browsing documentation and copying examples is easier without the redefine...
| NotAvailable, | ||
| /// Needs (re)seeding. Depending on the RNG this can mean you have to wait | ||
| /// and retry later, or you have to (re)seed it. | ||
| EntropyLow, |
There was a problem hiding this comment.
Not so keen on the doc or name for this one, and not sure if the two different things should be combined anyway — what's the advantage?
Possible doc: For PRNGs, this implies they should be (re)seeded. For external RNGs (e.g. OsRng) this implies you should wait and try again later.
| pub type Result<T> = ::std::result::Result<T, Error>; | ||
| fn cause(&self) -> Option<&::std::error::Error> { | ||
| None | ||
| } |
There was a problem hiding this comment.
I don't think there's any point implementing cause if it just returns None; this is the default impl.
There was a problem hiding this comment.
Didn't notice that. No, than I can happily remove it
|
Ok, removing the |
Yes, the discussion has died down a bit, but I agree there are still some things open. I also have some unposted comments on my pc about it, that need finishing :-). After playing with this Error enum a bit more, I miss that it can not return a cause. What do you think about a struct with this enum and a cause when using |
|
Regarding my previous comment — any chance you can split this PR? I hate reviewing stuff this big. But also it might be better to merge the Isaac stuff first. |
I was careful to split the PR in 3 commits. Each should be the smallest change that keeps building. It is your call. Shall I remove the second two commits, and make PR's for them when this one lands? |
dhardy
left a comment
There was a problem hiding this comment.
Couple of minor things. Looks like two of my comments were addressed by a later commit.
| } | ||
|
|
||
| let reader = File::open("/dev/urandom")?; | ||
| let reader = File::open("/dev/urandom").unwrap(); |
| pub fn new() -> Result<OsRng> { | ||
| let reader = File::open("rand:")?; | ||
| pub fn new() -> Result<OsRng, Error> { | ||
| let reader = File::open("rand:").unwrap(); |
| } | ||
| pub fn try_fill(&mut self, v: &mut [u8]) -> Result<()> { | ||
| for s in v.chunks_mut(fuchsia_zircon::ZX_CPRNG_DRAW_MAX_LEN) { | ||
| pub fn try_fill(&mut self, v: &mut [u8]) -> Result<(), Error> { |
| match r.read(buf) { | ||
| Ok(0) => return Err(Error::new(ErrorKind::Unavailable, None)), | ||
| Ok(n) => buf = &mut mem::replace(&mut buf, &mut [])[n..], | ||
| Err(_) => return Err(Error::new(ErrorKind::Other, None)), |
There was a problem hiding this comment.
Err(e) => return Err(Error::new(ErrorKind::Other, Box::new(e)))
| 0 => return Err(Error), | ||
| n => buf = &mut mem::replace(&mut buf, &mut [])[n..], | ||
| match r.read(buf) { | ||
| Ok(0) => return Err(Error::new(ErrorKind::Unavailable, None)), |
There was a problem hiding this comment.
Nothing you can do with the given error type, but it does feel like the cause is missing here
There was a problem hiding this comment.
It is fixed in the third commit, that gives ReadRng better error handling
| fn try_fill(&mut self, dest: &mut [u8]) -> Result<(), Error>; | ||
| fn try_fill(&mut self, dest: &mut [u8]) -> Result<(), Error> { | ||
| Ok(self.fill_bytes(dest)) | ||
| } |
There was a problem hiding this comment.
Default impl... I'd like not to have this
There was a problem hiding this comment.
Maybe we can discuss it in #12? Personally I don't see a problem, but I may be missing something.
|
For |
Also moved the `impl_uint_from_fill` macro from `os.rs` to `randcore`. I had to modify its error handling anyway, and it is shared with `OsRng`.
|
Removed the default implementation of |
|
Yes, I guess so. I'll merge this. Do a merge commit rather than a rebase on your other branch please. |
This PR tries out some of the error handling we seem to be arriving at in the RFC tread.
For the error enum I have now:
It occurred to me the variants
EntropyExhaustedandNetYetSeededon the RFC thread are essentially the same, so I combined them intoEntropyLow.This commit partly undoes your work in 0a97209, I am sorry.
Maybe it is just me being to inexperienced, but the
Resultwith two arguments looks clearer to me. I think it helps documentation-wise, as you can now click on the return typeRngErrorin rustdoc and see the various causes. Because we have only four different methods that can return aResult, it does not really seem an ergonomic loss.The second commit adds back
fill_bytes. I gavetry_filla default implementation in terms offill_bytes. This makes implementation of PRNGs (which usually never error) slightly simpler, as they don't have to use Result. Wrappers become slightly more complex, as they have to wrap another method.In the third commit I tried out the new error handling with
ReadRng.Actually I was working on the
OsRngimplementations, and did not plan on writing this :-).So I have not touched the code in
os.rsthat much yet.