Error Handling with Result
Result<T, E>, the ? operator, custom error types, and when to panic.
Rust has no exceptions. Operations that can fail return Result<T, E>: Ok(value) or Err(error). The ? operator passes errors up to the caller in one character, and the compiler warns if you ignore a Result. Truly unexpected situations (bugs) panic instead.
Parsing sensor lines
ReadingError lists everything that can go wrong; Display gives each case a message.
ok_or(...)? turns a missing field into an error and returns it immediately.
value.parse()? produces a ParseFloatError, converted into ReadingError by the From implementation.
catch_unwind is used here only to show that indexing past the end panics; normal code lets panics end the program.
Result or panic?
let t: f64 = text.parse().unwrap(); // crashes on bad input let t: f64 = text.parse()?; // or match / map_err
Input from outside the program is expected to be wrong sometimes. Propagate or handle the error instead of panicking.
What does the ? operator do?
On Ok(v) it evaluates to v; on Err(e) it converts e with From into the function's error type and returns it immediately. On Option it returns None early.
When is panicking appropriate?
When a bug or broken invariant is detected (something that should be impossible), in tests, and in quick prototypes — not for expected failures such as invalid user input.