-
Notifications
You must be signed in to change notification settings - Fork 8
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
Remove panicking behavior #17
Conversation
To be clear: The library doesn't currently panic if the CRC is wrong, only if a wrong buffer size is passed. IMO panics can and should be used if the error is a clear developer error which should never happen if the calling code is correct. In this example providing buffers which have the wrong size. But maybe it would be better to use the type system to encode the constrains? So a buffer type that assures that it contains a reference to a slice which has a multiple of 3 bytes? cc @dbrgn for further inspiration about the topic 🙂 |
Is there a use case for a driver that creates dynamically sized buffers, which are then passed directly to If not, I'd keep the panics, since they simply ensure that invariants are honored. (In the Sensirion device drivers that I wrote, the size is always known in advance.) |
Fair point! The way I see it, with result types, the user can at least still decide to panic with unwrap or try to handle the error somehow.
I think that's the case for mine too? https://github.com/barafael/sdp8xx/blob/0e2ff653d0309866412b37a413261adeeac977f7/src/lib.rs#L148 Don't know if I want to entrust the compiler to see that though. Please ignore my bone-headedness, I can still just use my fork, or probably embrace the panic. (BTW, the sdp800 sensor is really fantastic) |
Well, if this invariant (buffer size must be a multiple of 3) is broken, then that's a hard programming error, and no type of error handling will get you out of that. However, it could be argued that especially on embedded, you might want to catch even unexpected programming errors in a seldomly used branch of the code and do some error handling that wouldn't be easily possible with panics. I guess since an assert is used, and not a debug assert, there's no runtime difference between the two variants. |
Would you be open to discuss improving the error handling of this crate, though? Unless I am doing something wrong, it's cumbersome. Say I have a |
We could do a simple newtype style wrapper though (dumping code from brain without compiling / testing 😉): struct I2CBuffer<'a>(&'a[u8])
impl<'a> TryFrom<&'a[u8]> {
fn from(...) -> Result<> {
}
} That way one could have a guarantee that the buffer is a multiple of three bytes and users could just unwrap the try from. How does this sound? |
Thanks ❤️ |
Sure.
I'm not sure I follow. crc8::validate looks like this: pub fn validate(buf: &[u8]) -> Result<(), ()> { If I recall correctly my line of thinking was, that it can just either succeed or fail, so we just return a I'd propose that we add an separate enum |
Sounds good to me... Although I have to say I have no idea how to do cross-crate error handling well. It is interesting that there is not a Regarding the |
I started #18 to add the |
I have tried implementing your suggestion for the I2CBuffer struct. Had trouble with the generic arguments I2cWrite and I2cRead, so had to make another enum and conversion...: |
I'd suggest to use the I2CBuffer then directly in the |
I have tried following your suggestion but ran into this problem:
Defining a |
Uh good point. I think we'd actually need two wrapper buffers then (Similar to |
Do you want to open a new pull request with your experiments regarding |
Hi,
thanks for taking the time to make a Rust library for your I2C sensors!
I think this no_std library should not panic when a wrong buffer size is passed, or if a crc is wrong. Instead, the methods already return Result, so I extended the Error type. Tests are adapted too.
I split the Error type in crc8::Error and crate::Error (the crc8 module has it's own Error type) because I didn't want crc8 to require embedded_hal::i2c etc. Please let me know if you know a better way.