stm32bluepill-mynewt-sensor
stm32bluepill-mynewt-sensor copied to clipboard
Proper error handling
https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/f51e0784957723fcea8d3efaec10cbaacd1d8048/src/send_coap.rs#L19-L23
Immediatly as I saw the video in the medium post I shuddered.
Do proper error handling in Rust!
Don't return int
s to indicate errors or failures, use Result<(), ErrorType>
instead. This is just one place, but everywhere where you have those ghastly assert!(rc == 0)
things, throw them away and burn them! Either use unwrap
, or better expect
.
More examples:
https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/f51e0784957723fcea8d3efaec10cbaacd1d8048/src/send_coap.rs#L34-L37
https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/f51e0784957723fcea8d3efaec10cbaacd1d8048/src/listen_sensor.rs#L30
https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/f51e0784957723fcea8d3efaec10cbaacd1d8048/src/listen_sensor.rs#L70
(why is that one declared as extern
although it's not pub
?)
https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/f51e0784957723fcea8d3efaec10cbaacd1d8048/src/send_coap.rs#L20
https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/f51e0784957723fcea8d3efaec10cbaacd1d8048/src/send_coap.rs#L34
and finally you can convert the integer error codes to an enum
https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/f51e0784957723fcea8d3efaec10cbaacd1d8048/src/sensor.rs#L123-L139
Hi Marcel: Thanks for the tip! The porting of the entire application from C to Rust is still in progress, once I'm done with the meaty parts (e.g. CoAP messaging), I'll come back to the return types. And write an article about this too!
Here's different pattern for returning results: https://rust-embedded.github.io/book/static-guarantees/design-contracts.html
impl<IN_MODE> GpioConfig<Enabled, Input, IN_MODE> {
pub fn into_input_pull_down(self) -> GpioConfig<Enabled, Input, PulledLow> {
....
// Pull down the GPIO pin
let pulled_low = input_pin.into_input_pull_down();
Any update operation on GpioConfig
returns another GpioConfig
object. It's like a chainable API.
Wonder if you have any thoughts on this approach?
Also what do you think about error-chain
?
http://brson.github.io/2016/11/30/starting-with-error-chain
Here's different pattern for returning results
No, that's not returning a Result
(as you can see by the return type). It's just returning a struct.
Also what do you think about
error-chain
?http://brson.github.io/2016/11/30/starting-with-error-chain
IIRC error-chain
is no longer recommended for new designs. You can of course roll your own Error enum, which should be no problem at all. You don't need a framework. You don't get any real benefits from it when working on an embedded platform.
Thanks Marcel, I'm testing expect() like this...
pub fn start_network_task() -> Result<(), i32> { // Returns an error code upon error.
Ok(())
}
// In main()
let rc = start_network_task();
rc.expect("");
When I did this, the compiled ROM size bloated from 55 KB to 58 KB. I suspect this could be due to core::fmt, I need to check.
Any idea how I can cut this bloat?
I hope you are compiling with --release
.
expect("")
should be expect("start_network_task failed")
or similar.
https://docs.rust-embedded.org/book/start/panicking.html could help
Hmmm wonder why Result
and expect()
would cause this bloat compared with returning ints. Aren't they functionally equivalent?
That's one of the reasons I didn't include this for the article. Needs more investigation. For embedded systems, this kind of unexplained bloat could be showstoppers.
Thanks for your help! :-)
Personally, I would not avoid using a Result
even if that means, that by binary increases by a few kb.
warning: unused
std::result::Result
that must be used
That's the most amazing thing! If you forget to use the Result
, the compiler will tell you. When you return an int, you don't need to handle it and you can easily swallow them. Also it doesn't tell you right away, what happened. It's just a convention that 0 means OK and any other values means Error. With Result
you get it with the type system. Amazing!