From ba94df655ef4a06d9fbe0374b8eb51f44c947389 Mon Sep 17 00:00:00 2001 From: Ludwig PACIFICI Date: Sat, 18 Nov 2017 15:51:49 +0000 Subject: [PATCH] Add "Avoid discarding errors during error conversions" example (#368) fixes #215 --- src/basics.md | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/intro.md | 2 ++ 2 files changed, 74 insertions(+) diff --git a/src/basics.md b/src/basics.md index dbd112a..6e0b587 100644 --- a/src/basics.md +++ b/src/basics.md @@ -25,6 +25,7 @@ | [Define and operate on a type represented as a bitfield][ex-bitflags] | [![bitflags-badge]][bitflags] | [![cat-no-std-badge]][cat-no-std] | | [Access a file randomly using a memory map][ex-random-file-access] | [![memmap-badge]][memmap] | [![cat-filesystem-badge]][cat-filesystem] | | [Check number of logical cpu cores][ex-check-cpu-cores] | [![num_cpus-badge]][num_cpus] | [![cat-hardware-support-badge]][cat-hardware-support] | +| [Avoid discarding errors during error conversions][ex-error-chain-avoid-discarding] | [![error-chain-badge]][error-chain] | [![cat-rust-patterns-badge]][cat-rust-patterns] | | [Obtain backtrace of complex error scenarios][ex-error-chain-backtrace] | [![error-chain-badge]][error-chain] | [![cat-rust-patterns-badge]][cat-rust-patterns] | | [Measure elapsed time][ex-measure-elapsed-time] | [![std-badge]][std] | [![cat-time-badge]][cat-time] | | [Convert date to UNIX timestamp and vice versa][ex-convert-datetime-timestamp] | [![chrono-badge]][chrono] | [![cat-date-and-time-badge]][cat-date-and-time] | @@ -1145,6 +1146,74 @@ fn main() { } ``` +[ex-error-chain-avoid-discarding]: #ex-error-chain-avoid-discarding + +## Avoid discarding errors during error conversions + +[![error-chain-badge]][error-chain] [![cat-rust-patterns-badge]][cat-rust-patterns] + +[Matching] on different error types returned by a function is possible +and relatively compact with [error-chain] crate. To do so, +[`ErrorKind`] is used to determine the error type. + +To illustrate the error matching, a random integer generator web +service will be queried via [reqwest] and then the response will be +parsed. Errors can be generated by the Rust standard library, +[reqwest] and by the web service. [`foreign_links`] are used for well +defined Rust errors. The `errors` block of the `error_chain!` macro is +used to create an additional [`ErrorKind`] variant for the web service +error. Finally, a regular `match` can be used to react differently +according to the raised error. + +```rust +#[macro_use] +extern crate error_chain; +extern crate reqwest; + +use std::io::Read; + +error_chain! { + foreign_links { + Io(std::io::Error); + Reqwest(reqwest::Error); + ParseIntError(std::num::ParseIntError); + } + + errors { RandomResponseError(t: String) } +} + +fn parse_response(mut response: reqwest::Response) -> Result { + let mut body = String::new(); + response.read_to_string(&mut body)?; + body.pop(); + body.parse::() + .chain_err(|| ErrorKind::RandomResponseError(body)) +} + +fn run() -> Result<()> { + let url = + format!("https://www.random.org/integers/?num=1&min=0&max=10&col=1&base=10&format=plain"); + let response = reqwest::get(&url)?; + let random_value: u32 = parse_response(response)?; + + println!("a random number between 0 and 10: {}", random_value); + + Ok(()) +} + +fn main() { + if let Err(error) = run() { + match *error.kind() { + ErrorKind::Io(_) => println!("Standard IO error: {:?}", error), + ErrorKind::Reqwest(_) => println!("Reqwest error: {:?}", error), + ErrorKind::ParseIntError(_) => println!("Standard parse int error: {:?}", error), + ErrorKind::RandomResponseError(_) => println!("User defined error: {:?}", error), + _ => println!("Other error: {:?}", error), + } + } +} +``` + [ex-error-chain-backtrace]: #ex-error-chain-backtrace ## Obtain backtrace of complex error scenarios @@ -1514,14 +1583,17 @@ fn main() { [`digest::Context`]: https://docs.rs/ring/*/ring/digest/struct.Context.html [`digest::Digest`]: https://docs.rs/ring/*/ring/digest/struct.Digest.html [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html +[`ErrorKind`]: https://docs.rs/error-chain/*/error_chain/example_generated/enum.ErrorKind.html [`File::create`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.create [`File::open`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.open [`File::try_clone`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.try_clone [`File`]: https://doc.rust-lang.org/std/fs/struct.File.html +[`foreign_links`]: https://docs.rs/error-chain/*/error_chain/#foreign-links [`HashMap`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html [`hmac::Signature`]: https://docs.rs/ring/*/ring/hmac/struct.Signature.html [`IndependentSample::ind_sample`]: https://doc.rust-lang.org/rand/rand/distributions/trait.IndependentSample.html#tymethod.ind_sample [`Lines`]: https://doc.rust-lang.org/std/io/struct.Lines.html +[Matching]:https://docs.rs/error-chain/*/error_chain/#matching-errors [`Mmap::map`]: https://docs.rs/memmap/*/memmap/struct.Mmap.html#method.map [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html [`MutexGuard`]: https://doc.rust-lang.org/std/sync/struct.MutexGuard.html diff --git a/src/intro.md b/src/intro.md index e031a0b..117c3c8 100644 --- a/src/intro.md +++ b/src/intro.md @@ -43,6 +43,7 @@ community. It needs and welcomes help. For details see | [Define and operate on a type represented as a bitfield][ex-bitflags] | [![bitflags-badge]][bitflags] | [![cat-no-std-badge]][cat-no-std] | | [Access a file randomly using a memory map][ex-random-file-access] | [![memmap-badge]][memmap] | [![cat-filesystem-badge]][cat-filesystem] | | [Check number of logical cpu cores][ex-check-cpu-cores] | [![num_cpus-badge]][num_cpus] | [![cat-hardware-support-badge]][cat-hardware-support] | +| [Avoid discarding errors during error conversions][ex-error-chain-avoid-discarding] | [![error-chain-badge]][error-chain] | [![cat-rust-patterns-badge]][cat-rust-patterns] | | [Obtain backtrace of complex error scenarios][ex-error-chain-backtrace] | [![error-chain-badge]][error-chain] | [![cat-rust-patterns-badge]][cat-rust-patterns] | | [Measure elapsed time][ex-measure-elapsed-time] | [![std-badge]][std] | [![cat-time-badge]][cat-time] | | [Convert date to UNIX timestamp and vice versa][ex-convert-datetime-timestamp] | [![chrono-badge]][chrono] | [![cat-date-and-time-badge]][cat-date-and-time] | @@ -172,6 +173,7 @@ community. It needs and welcomes help. For details see [ex-csv-serde]: encoding.html#ex-csv-serde [ex-datetime-arithmetic]: basics.html#ex-datetime-arithmetic [ex-dedup-filenames]: app.html#ex-dedup-filenames +[ex-error-chain-avoid-discarding]: basics.html#ex-error-chain-avoid-discarding [ex-error-chain-backtrace]: basics.html#ex-error-chain-backtrace [ex-examine-date-and-time]: basics.html#ex-examine-date-and-time [ex-extract-hashtags]: basics.html#ex-extract-hashtags