mirror of
https://github.com/haraldh/chainerror.git
synced 2025-06-06 16:14:43 +02:00
parent
719e221e4b
commit
5c93f1a5fe
21 changed files with 11008 additions and 793 deletions
594
tutorial11.html
594
tutorial11.html
|
@ -3,9 +3,9 @@
|
|||
<head>
|
||||
<!-- Book generated using mdBook -->
|
||||
<meta charset="UTF-8">
|
||||
<title>Chapter 11 - chainerror</title>
|
||||
<title>Debug for the ErrorKind - chainerror</title>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="description" content="">
|
||||
<meta name="description" content="A tutorial for the chainerror rust crate.">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
|
||||
|
@ -75,7 +75,7 @@
|
|||
</script>
|
||||
|
||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||
<ol class="chapter"><li><a href="tutorial1.html"><strong aria-hidden="true">1.</strong> Chapter 1</a></li><li><a href="tutorial2.html"><strong aria-hidden="true">2.</strong> Chapter 2</a></li><li><a href="tutorial3.html"><strong aria-hidden="true">3.</strong> Chapter 3</a></li><li><a href="tutorial4.html"><strong aria-hidden="true">4.</strong> Chapter 4</a></li><li><a href="tutorial5.html"><strong aria-hidden="true">5.</strong> Chapter 5</a></li><li><a href="tutorial6.html"><strong aria-hidden="true">6.</strong> Chapter 6</a></li><li><a href="tutorial7.html"><strong aria-hidden="true">7.</strong> Chapter 7</a></li><li><a href="tutorial8.html"><strong aria-hidden="true">8.</strong> Chapter 8</a></li><li><a href="tutorial9.html"><strong aria-hidden="true">9.</strong> Chapter 9</a></li><li><a href="tutorial10.html"><strong aria-hidden="true">10.</strong> Chapter 10</a></li><li><a href="tutorial11.html" class="active"><strong aria-hidden="true">11.</strong> Chapter 11</a></li></ol>
|
||||
<ol class="chapter"><li class="affix"><a href="index.html">chainerror</a></li><li><a href="tutorial1.html"><strong aria-hidden="true">1.</strong> Simple String Errors</a></li><li><a href="tutorial2.html"><strong aria-hidden="true">2.</strong> Simple Chained String Errors</a></li><li><a href="tutorial3.html"><strong aria-hidden="true">3.</strong> Mapping Errors</a></li><li><a href="tutorial4.html"><strong aria-hidden="true">4.</strong> Saving coding chars</a></li><li><a href="tutorial5.html"><strong aria-hidden="true">5.</strong> The source() of Errors</a></li><li><a href="tutorial6.html"><strong aria-hidden="true">6.</strong> Downcast the Errors</a></li><li><a href="tutorial7.html"><strong aria-hidden="true">7.</strong> The root cause of all Errors</a></li><li><a href="tutorial8.html"><strong aria-hidden="true">8.</strong> Finding an Error cause</a></li><li><a href="tutorial9.html"><strong aria-hidden="true">9.</strong> Selective Error Handling</a></li><li><a href="tutorial10.html"><strong aria-hidden="true">10.</strong> ErrorKind to the rescue</a></li><li><a href="tutorial11.html" class="active"><strong aria-hidden="true">11.</strong> Debug for the ErrorKind</a></li><li class="affix"><a href="end.html">The End</a></li></ol>
|
||||
</nav>
|
||||
|
||||
<div id="page-wrapper" class="page-wrapper">
|
||||
|
@ -141,7 +141,18 @@
|
|||
<div id="content" class="content">
|
||||
<main>
|
||||
<a class="header" href="#debug-for-the-errorkind" id="debug-for-the-errorkind"><h1>Debug for the ErrorKind</h1></a>
|
||||
<p>[TBD]</p>
|
||||
<p>One small improvement at the end of the tutorial is to fix the debug output of
|
||||
<code>Func1ErrorKind</code>. As you probably noticed, the output doesn't say much of the enum.</p>
|
||||
<pre><code>Debug Error:
|
||||
src/main.rs:35: Func2
|
||||
[…]
|
||||
</code></pre>
|
||||
<p>As a lazy shortcut, we implement <code>Debug</code> by calling <code>Display</code> and end up with</p>
|
||||
<pre><code>Debug Error:
|
||||
src/main.rs:40: func1 error calling func2
|
||||
[…}
|
||||
</code></pre>
|
||||
<p>which gives us a lot more detail.</p>
|
||||
<pre><pre class="playpen"><code class="language-rust">use crate::chainerror::*;
|
||||
use std::error::Error;
|
||||
use std::io;
|
||||
|
@ -160,44 +171,44 @@ fn func2() -> Result<(), Box<Error>> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
enum Func1Error {
|
||||
enum Func1ErrorKind {
|
||||
Func2,
|
||||
IO(String),
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for Func1Error {
|
||||
impl ::std::fmt::Display for Func1ErrorKind {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
match self {
|
||||
Func1Error::Func2 => write!(f, "func1 error calling func2"),
|
||||
Func1Error::IO(filename) => write!(f, "Error reading '{}'", filename),
|
||||
Func1ErrorKind::Func2 => write!(f, "func1 error calling func2"),
|
||||
Func1ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Debug for Func1Error {
|
||||
impl ::std::fmt::Debug for Func1ErrorKind {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
write!(f, "{}", self)
|
||||
}
|
||||
}
|
||||
|
||||
fn func1() -> ChainResult<(), Func1Error> {
|
||||
func2().map_err(|e| cherr!(e, Func1Error::Func2))?;
|
||||
fn func1() -> ChainResult<(), Func1ErrorKind> {
|
||||
func2().map_err(|e| cherr!(e, Func1ErrorKind::Func2))?;
|
||||
let filename = String::from("bar.txt");
|
||||
do_some_io().map_err(|e| cherr!(e, Func1Error::IO(filename)))?;
|
||||
do_some_io().map_err(|e| cherr!(e, Func1ErrorKind::IO(filename)))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<Error>> {
|
||||
if let Err(e) = func1() {
|
||||
match e.kind() {
|
||||
Func1Error::Func2 => eprintln!("Main Error Report: func1 error calling func2"),
|
||||
Func1Error::IO(filename) => {
|
||||
Func1ErrorKind::Func2 => eprintln!("Main Error Report: func1 error calling func2"),
|
||||
Func1ErrorKind::IO(filename) => {
|
||||
eprintln!("Main Error Report: func1 error reading '{}'", filename)
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(e) = e.find_chain_cause::<Func2Error>() {
|
||||
eprintln!("Error reported by Func2Error: {}", e)
|
||||
eprintln!("\nError reported by Func2Error: {}", e)
|
||||
}
|
||||
|
||||
eprintln!("\nDebug Error:\n{:?}", e);
|
||||
|
@ -206,10 +217,167 @@ fn main() -> Result<(), Box<Error>> {
|
|||
}
|
||||
# #[allow(dead_code)]
|
||||
# mod chainerror {
|
||||
# /*!
|
||||
#
|
||||
# `chainerror` provides an error backtrace without doing a real backtrace, so even after you `strip` your
|
||||
# binaries, you still have the error backtrace.
|
||||
#
|
||||
# `chainerror` has no dependencies!
|
||||
#
|
||||
# `chainerror` uses `.source()` of `std::error::Error` along with `line()!` and `file()!` to provide a nice debug error backtrace.
|
||||
# It encapsulates all types, which have `Display + Debug` and can store the error cause internally.
|
||||
#
|
||||
# Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.
|
||||
#
|
||||
# # Examples
|
||||
#
|
||||
# ~~~rust
|
||||
# use chainerror::*;
|
||||
# use std::error::Error;
|
||||
# use std::io;
|
||||
# use std::result::Result;
|
||||
#
|
||||
# fn do_some_io() -> Result<(), Box<Error>> {
|
||||
# Err(io::Error::from(io::ErrorKind::NotFound))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# fn func2() -> Result<(), Box<Error>> {
|
||||
# let filename = "foo.txt";
|
||||
# do_some_io().map_err(mstrerr!("Error reading '{}'", filename))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# fn func1() -> Result<(), Box<Error>> {
|
||||
# func2().map_err(mstrerr!("func1 error"))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# fn main() {
|
||||
# if let Err(e) = func1() {
|
||||
# assert_eq!(
|
||||
# format!("\n{:?}\n", e), r#"
|
||||
# src/lib.rs:20: func1 error
|
||||
# Caused by:
|
||||
# src/lib.rs:15: Error reading 'foo.txt'
|
||||
# Caused by:
|
||||
# Kind(NotFound)
|
||||
# "#
|
||||
# );
|
||||
# }
|
||||
# # else {
|
||||
# # unreachable!();
|
||||
# # }
|
||||
# }
|
||||
# ~~~
|
||||
#
|
||||
#
|
||||
# ~~~rust
|
||||
# use chainerror::*;
|
||||
# use std::error::Error;
|
||||
# use std::io;
|
||||
# use std::result::Result;
|
||||
#
|
||||
# fn do_some_io() -> Result<(), Box<Error>> {
|
||||
# Err(io::Error::from(io::ErrorKind::NotFound))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# fn func3() -> Result<(), Box<Error>> {
|
||||
# let filename = "foo.txt";
|
||||
# do_some_io().map_err(mstrerr!("Error reading '{}'", filename))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# derive_str_cherr!(Func2Error);
|
||||
#
|
||||
# fn func2() -> ChainResult<(), Func2Error> {
|
||||
# func3().map_err(mstrerr!(Func2Error, "func2 error: calling func3"))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# enum Func1Error {
|
||||
# Func2,
|
||||
# IO(String),
|
||||
# }
|
||||
#
|
||||
# impl ::std::fmt::Display for Func1Error {
|
||||
# fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
# match self {
|
||||
# Func1Error::Func2 => write!(f, "func1 error calling func2"),
|
||||
# Func1Error::IO(filename) => write!(f, "Error reading '{}'", filename),
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# impl ::std::fmt::Debug for Func1Error {
|
||||
# fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
# write!(f, "{}", self)
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# fn func1() -> ChainResult<(), Func1Error> {
|
||||
# func2().map_err(|e| cherr!(e, Func1Error::Func2))?;
|
||||
# let filename = String::from("bar.txt");
|
||||
# do_some_io().map_err(|e| cherr!(e, Func1Error::IO(filename)))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# fn main() {
|
||||
# if let Err(e) = func1() {
|
||||
# assert!(
|
||||
# match e.kind() {
|
||||
# Func1Error::Func2 => {
|
||||
# eprintln!("Main Error Report: func1 error calling func2");
|
||||
# true
|
||||
# }
|
||||
# Func1Error::IO(filename) => {
|
||||
# eprintln!("Main Error Report: func1 error reading '{}'", filename);
|
||||
# false
|
||||
# }
|
||||
# }
|
||||
# );
|
||||
#
|
||||
# assert!(e.find_chain_cause::<Func2Error>().is_some());
|
||||
#
|
||||
# if let Some(e) = e.find_chain_cause::<Func2Error>() {
|
||||
# eprintln!("\nError reported by Func2Error: {}", e)
|
||||
# }
|
||||
#
|
||||
#
|
||||
# assert!(e.root_cause().is_some());
|
||||
#
|
||||
# if let Some(e) = e.root_cause() {
|
||||
# let ioerror = e.downcast_ref::<io::Error>().unwrap();
|
||||
# eprintln!("\nThe root cause was: std::io::Error: {:#?}", ioerror);
|
||||
# }
|
||||
#
|
||||
# assert_eq!(
|
||||
# format!("\n{:?}\n", e), r#"
|
||||
# src/lib.rs:47: func1 error calling func2
|
||||
# Caused by:
|
||||
# src/lib.rs:22: Func2Error(func2 error: calling func3)
|
||||
# Caused by:
|
||||
# src/lib.rs:15: Error reading 'foo.txt'
|
||||
# Caused by:
|
||||
# Kind(NotFound)
|
||||
# "#
|
||||
# );
|
||||
# }
|
||||
# # else {
|
||||
# # unreachable!();
|
||||
# # }
|
||||
# }
|
||||
# ~~~
|
||||
#
|
||||
# !*/
|
||||
#
|
||||
# use std::any::TypeId;
|
||||
# use std::error::Error;
|
||||
# use std::fmt::{Debug, Display, Formatter, Result};
|
||||
# use std::result::Result as StdResult;
|
||||
#
|
||||
# /** chains an inner error kind `T` with a causing error
|
||||
# **/
|
||||
# pub struct ChainError<T> {
|
||||
# #[cfg(not(feature = "no-fileline"))]
|
||||
# occurrence: Option<(u32, &'static str)>,
|
||||
|
@ -217,10 +385,12 @@ fn main() -> Result<(), Box<Error>> {
|
|||
# error_cause: Option<Box<dyn Error + 'static>>,
|
||||
# }
|
||||
#
|
||||
# pub type ChainResult<O, E> = StdResult<O, ChainError<E>>;
|
||||
# /// convenience type alias
|
||||
# pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;
|
||||
#
|
||||
# impl<T: 'static + Display + Debug> ChainError<T> {
|
||||
# #[cfg(not(feature = "no-fileline"))]
|
||||
# /// Use the `cherr!()` or `mstrerr!()` macro instead of calling this directly
|
||||
# pub fn new(
|
||||
# kind: T,
|
||||
# error_cause: Option<Box<dyn Error + 'static>>,
|
||||
|
@ -234,6 +404,7 @@ fn main() -> Result<(), Box<Error>> {
|
|||
# }
|
||||
#
|
||||
# #[cfg(feature = "no-fileline")]
|
||||
# /// Use the `cherr!()` or `mstrerr!()` macro instead of calling this directly
|
||||
# pub fn new(
|
||||
# kind: T,
|
||||
# error_cause: Option<Box<dyn Error + 'static>>,
|
||||
|
@ -242,6 +413,7 @@ fn main() -> Result<(), Box<Error>> {
|
|||
# Self { kind, error_cause }
|
||||
# }
|
||||
#
|
||||
# /// return the root cause of the error chain, if any exists
|
||||
# pub fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
|
||||
# let mut cause = self as &(dyn Error + 'static);
|
||||
# while let Some(c) = cause.source() {
|
||||
|
@ -250,6 +422,54 @@ fn main() -> Result<(), Box<Error>> {
|
|||
# Some(cause)
|
||||
# }
|
||||
#
|
||||
# /** find the first error cause of type U, if any exists
|
||||
#
|
||||
# # Examples
|
||||
#
|
||||
# ~~~rust
|
||||
# # use crate::chainerror::*;
|
||||
# # use std::error::Error;
|
||||
# # use std::io;
|
||||
# # use std::result::Result;
|
||||
# #
|
||||
# fn do_some_io() -> Result<(), Box<Error>> {
|
||||
# Err(io::Error::from(io::ErrorKind::NotFound))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# derive_str_cherr!(Func2Error);
|
||||
#
|
||||
# fn func2() -> Result<(), Box<Error>> {
|
||||
# let filename = "foo.txt";
|
||||
# do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# derive_str_cherr!(Func1Error);
|
||||
#
|
||||
# fn func1() -> Result<(), Box<Error>> {
|
||||
# func2().map_err(mstrerr!(Func1Error, "func1 error"))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# fn main() {
|
||||
# if let Err(e) = func1() {
|
||||
# if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
|
||||
#
|
||||
# assert!(f1err.find_cause::<io::Error>().is_some());
|
||||
#
|
||||
# assert!(f1err.find_chain_cause::<Func2Error>().is_some());
|
||||
# }
|
||||
# # else {
|
||||
# # panic!();
|
||||
# # }
|
||||
# }
|
||||
# # else {
|
||||
# # unreachable!();
|
||||
# # }
|
||||
# }
|
||||
# ~~~
|
||||
# **/
|
||||
# pub fn find_cause<U: Error + 'static>(&self) -> Option<&U> {
|
||||
# let mut cause = self as &(dyn Error + 'static);
|
||||
# loop {
|
||||
|
@ -264,6 +484,21 @@ fn main() -> Result<(), Box<Error>> {
|
|||
# }
|
||||
# }
|
||||
#
|
||||
# /** find the first error cause of type ChainError<U>, if any exists
|
||||
#
|
||||
# Same as `find_cause`, but hides the `ChainError<U>` implementation internals
|
||||
#
|
||||
# # Examples
|
||||
#
|
||||
# ~~~rust,ignore
|
||||
# /// Instead of writing
|
||||
# err.find_cause::<ChainError<FooError>>();
|
||||
#
|
||||
# /// leave out the ChainError<T> implementation detail
|
||||
# err.find_chain_cause::<FooError>();
|
||||
# ~~~
|
||||
#
|
||||
# **/
|
||||
# pub fn find_chain_cause<U: Error + 'static>(&self) -> Option<&ChainError<U>> {
|
||||
# let mut cause = self as &(dyn Error + 'static);
|
||||
# loop {
|
||||
|
@ -278,19 +513,84 @@ fn main() -> Result<(), Box<Error>> {
|
|||
# }
|
||||
# }
|
||||
#
|
||||
# /** return a reference to T of `ChainError<T>`
|
||||
#
|
||||
# # Examples
|
||||
#
|
||||
# ~~~rust
|
||||
# # use crate::chainerror::*;
|
||||
# # use std::error::Error;
|
||||
# # use std::io;
|
||||
# # use std::result::Result;
|
||||
# #
|
||||
# fn do_some_io() -> Result<(), Box<Error>> {
|
||||
# Err(io::Error::from(io::ErrorKind::NotFound))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# derive_str_cherr!(Func2Error);
|
||||
#
|
||||
# fn func2() -> Result<(), Box<Error>> {
|
||||
# let filename = "foo.txt";
|
||||
# do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# #[derive(Debug)]
|
||||
# enum Func1ErrorKind {
|
||||
# Func2,
|
||||
# IO(String),
|
||||
# }
|
||||
#
|
||||
# // impl ::std::fmt::Display for Func1ErrorKind {…}
|
||||
# # impl ::std::fmt::Display for Func1ErrorKind {
|
||||
# # fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
# # match self {
|
||||
# # Func1ErrorKind::Func2 => write!(f, "func1 error calling func2"),
|
||||
# # Func1ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename),
|
||||
# # }
|
||||
# # }
|
||||
# # }
|
||||
#
|
||||
# fn func1() -> ChainResult<(), Func1ErrorKind> {
|
||||
# func2().map_err(|e| cherr!(e, Func1ErrorKind::Func2))?;
|
||||
# do_some_io().map_err(|e| cherr!(e, Func1ErrorKind::IO("bar.txt".into())))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# fn main() {
|
||||
# if let Err(e) = func1() {
|
||||
# match e.kind() {
|
||||
# Func1ErrorKind::Func2 => {},
|
||||
# Func1ErrorKind::IO(filename) => panic!(),
|
||||
# }
|
||||
# }
|
||||
# # else {
|
||||
# # unreachable!();
|
||||
# # }
|
||||
# }
|
||||
# ~~~
|
||||
#
|
||||
# **/
|
||||
# pub fn kind<'a>(&'a self) -> &'a T {
|
||||
# &self.kind
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# /** convenience trait to hide the `ChainError<T>` implementation internals
|
||||
# **/
|
||||
# pub trait ChainErrorDown {
|
||||
# /** test if of type `ChainError<T>`
|
||||
# **/
|
||||
# fn is_chain<T: 'static + Display + Debug>(&self) -> bool;
|
||||
# /** downcast to a reference of `ChainError<T>`
|
||||
# **/
|
||||
# fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>>;
|
||||
# /** downcast to a mutable reference of `ChainError<T>`
|
||||
# **/
|
||||
# fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>>;
|
||||
# }
|
||||
#
|
||||
# use std::any::TypeId;
|
||||
#
|
||||
# impl<U: 'static + Display + Debug> ChainErrorDown for ChainError<U> {
|
||||
# fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
|
||||
# TypeId::of::<T>() == TypeId::of::<U>()
|
||||
|
@ -409,7 +709,11 @@ fn main() -> Result<(), Box<Error>> {
|
|||
# }
|
||||
# }
|
||||
#
|
||||
# Debug::fmt(&self.kind, f)?;
|
||||
# if self.is_chain::<String>() {
|
||||
# Display::fmt(&self.kind, f)?;
|
||||
# } else {
|
||||
# Debug::fmt(&self.kind, f)?;
|
||||
# }
|
||||
#
|
||||
# #[cfg(not(feature = "no-debug-cause"))]
|
||||
# {
|
||||
|
@ -422,6 +726,93 @@ fn main() -> Result<(), Box<Error>> {
|
|||
# }
|
||||
# }
|
||||
#
|
||||
# /** creates a new `ChainError<T>`
|
||||
#
|
||||
# # Examples
|
||||
#
|
||||
# Create a new ChainError<FooError>, where `FooError` must implement `Display` and `Debug`.
|
||||
# ~~~rust
|
||||
# # use chainerror::*;
|
||||
# #
|
||||
# # #[derive(Debug)]
|
||||
# enum FooError {
|
||||
# Bar,
|
||||
# Baz(&'static str),
|
||||
# }
|
||||
# #
|
||||
# # impl ::std::fmt::Display for FooError {
|
||||
# # fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
# # match self {
|
||||
# # FooError::Bar => write!(f, "Bar Error"),
|
||||
# # FooError::Baz(s) => write!(f, "Baz Error: '{}'", s),
|
||||
# # }
|
||||
# # }
|
||||
# # }
|
||||
#
|
||||
# // impl ::std::fmt::Display for FooError
|
||||
#
|
||||
# fn do_some_stuff() -> bool {
|
||||
# false
|
||||
# }
|
||||
#
|
||||
# fn func() -> ChainResult<(), FooError> {
|
||||
# if ! do_some_stuff() {
|
||||
# Err(cherr!(FooError::Baz("Error")))?;
|
||||
# }
|
||||
# Ok(())
|
||||
# }
|
||||
# #
|
||||
# # pub fn main() {
|
||||
# # match func().unwrap_err().kind() {
|
||||
# # FooError::Baz(s) if s == &"Error" => {},
|
||||
# # _ => panic!(),
|
||||
# # }
|
||||
# # }
|
||||
# ~~~
|
||||
#
|
||||
# Additionally an error cause can be added.
|
||||
#
|
||||
# ~~~rust
|
||||
# # use chainerror::*;
|
||||
# # use std::io;
|
||||
# # use std::error::Error;
|
||||
# #
|
||||
# # #[derive(Debug)]
|
||||
# # enum FooError {
|
||||
# # Bar,
|
||||
# # Baz(&'static str),
|
||||
# # }
|
||||
# #
|
||||
# # impl ::std::fmt::Display for FooError {
|
||||
# # fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
# # match self {
|
||||
# # FooError::Bar => write!(f, "Bar Error"),
|
||||
# # FooError::Baz(s) => write!(f, "Baz Error: '{}'", s),
|
||||
# # }
|
||||
# # }
|
||||
# # }
|
||||
# #
|
||||
# fn do_some_stuff() -> Result<(), Box<Error>> {
|
||||
# Err(io::Error::from(io::ErrorKind::NotFound))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# fn func() -> ChainResult<(), FooError> {
|
||||
# do_some_stuff().map_err(
|
||||
# |e| cherr!(e, FooError::Baz("Error"))
|
||||
# )?;
|
||||
# Ok(())
|
||||
# }
|
||||
# #
|
||||
# # pub fn main() {
|
||||
# # match func().unwrap_err().kind() {
|
||||
# # FooError::Baz(s) if s == &"Error" => {},
|
||||
# # _ => panic!(),
|
||||
# # }
|
||||
# # }
|
||||
# ~~~
|
||||
#
|
||||
# **/
|
||||
# #[macro_export]
|
||||
# macro_rules! cherr {
|
||||
# ( $k:expr ) => {
|
||||
|
@ -432,6 +823,92 @@ fn main() -> Result<(), Box<Error>> {
|
|||
# };
|
||||
# }
|
||||
#
|
||||
# /** convenience macro for |e| cherr!(e, format!(…))
|
||||
#
|
||||
# # Examples
|
||||
#
|
||||
# ~~~rust
|
||||
# # use crate::chainerror::*;
|
||||
# # use std::error::Error;
|
||||
# # use std::io;
|
||||
# # use std::result::Result;
|
||||
# #
|
||||
# # fn do_some_io() -> Result<(), Box<Error>> {
|
||||
# # Err(io::Error::from(io::ErrorKind::NotFound))?;
|
||||
# # Ok(())
|
||||
# # }
|
||||
# #
|
||||
# fn func2() -> Result<(), Box<Error>> {
|
||||
# let filename = "foo.txt";
|
||||
# do_some_io().map_err(mstrerr!("Error reading '{}'", filename))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# fn func1() -> Result<(), Box<Error>> {
|
||||
# func2().map_err(mstrerr!("func1 error"))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# # fn main() {
|
||||
# # if let Err(e) = func1() {
|
||||
# # assert_eq!(
|
||||
# # format!("\n{:?}\n", e), r#"
|
||||
# # src/lib.rs:20: func1 error
|
||||
# # Caused by:
|
||||
# # src/lib.rs:15: Error reading 'foo.txt'
|
||||
# # Caused by:
|
||||
# # Kind(NotFound)
|
||||
# # "#
|
||||
# # );
|
||||
# # } else {
|
||||
# # unreachable!();
|
||||
# # }
|
||||
# # }
|
||||
# ~~~
|
||||
#
|
||||
# `mstrerr!()` can also be used to map a new `ChainError<T>`, where T was defined with
|
||||
# `derive_str_cherr!(T)`
|
||||
#
|
||||
# ~~~rust
|
||||
# # use crate::chainerror::*;
|
||||
# # use std::error::Error;
|
||||
# # use std::io;
|
||||
# # use std::result::Result;
|
||||
# #
|
||||
# # fn do_some_io() -> Result<(), Box<Error>> {
|
||||
# # Err(io::Error::from(io::ErrorKind::NotFound))?;
|
||||
# # Ok(())
|
||||
# # }
|
||||
# #
|
||||
# derive_str_cherr!(Func2Error);
|
||||
#
|
||||
# fn func2() -> Result<(), Box<Error>> {
|
||||
# let filename = "foo.txt";
|
||||
# do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# derive_str_cherr!(Func1Error);
|
||||
#
|
||||
# fn func1() -> Result<(), Box<Error>> {
|
||||
# func2().map_err(mstrerr!(Func1Error, "func1 error"))?;
|
||||
# Ok(())
|
||||
# }
|
||||
# #
|
||||
# # fn main() {
|
||||
# # if let Err(e) = func1() {
|
||||
# # if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
|
||||
# # assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
|
||||
# # assert!(f1err.find_chain_cause::<Func2Error>().is_some());
|
||||
# # } else {
|
||||
# # panic!();
|
||||
# # }
|
||||
# # } else {
|
||||
# # unreachable!();
|
||||
# # }
|
||||
# # }
|
||||
# ~~~
|
||||
# **/
|
||||
# #[macro_export]
|
||||
# macro_rules! mstrerr {
|
||||
# ( $t:ident, $v:expr $(, $more:expr)* ) => {
|
||||
|
@ -445,6 +922,49 @@ fn main() -> Result<(), Box<Error>> {
|
|||
# };
|
||||
# }
|
||||
#
|
||||
# /** convenience macro to create a "new type" T(String) and implement Display + Debug for T
|
||||
#
|
||||
# ~~~rust
|
||||
# # use crate::chainerror::*;
|
||||
# # use std::error::Error;
|
||||
# # use std::io;
|
||||
# # use std::result::Result;
|
||||
# #
|
||||
# # fn do_some_io() -> Result<(), Box<Error>> {
|
||||
# # Err(io::Error::from(io::ErrorKind::NotFound))?;
|
||||
# # Ok(())
|
||||
# # }
|
||||
# #
|
||||
# derive_str_cherr!(Func2Error);
|
||||
#
|
||||
# fn func2() -> ChainResult<(), Func2Error> {
|
||||
# let filename = "foo.txt";
|
||||
# do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?;
|
||||
# Ok(())
|
||||
# }
|
||||
#
|
||||
# derive_str_cherr!(Func1Error);
|
||||
#
|
||||
# fn func1() -> Result<(), Box<Error>> {
|
||||
# func2().map_err(mstrerr!(Func1Error, "func1 error"))?;
|
||||
# Ok(())
|
||||
# }
|
||||
# #
|
||||
# # fn main() {
|
||||
# # if let Err(e) = func1() {
|
||||
# # if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
|
||||
# # assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
|
||||
# # assert!(f1err.find_chain_cause::<Func2Error>().is_some());
|
||||
# # } else {
|
||||
# # panic!();
|
||||
# # }
|
||||
# # } else {
|
||||
# # unreachable!();
|
||||
# # }
|
||||
# # }
|
||||
# ~~~
|
||||
#
|
||||
# **/
|
||||
# #[macro_export]
|
||||
# macro_rules! derive_str_cherr {
|
||||
# ($e:ident) => {
|
||||
|
@ -462,26 +982,6 @@ fn main() -> Result<(), Box<Error>> {
|
|||
# impl ::std::error::Error for $e {}
|
||||
# };
|
||||
# }
|
||||
#
|
||||
# #[macro_export]
|
||||
# macro_rules! try_cherr_ref {
|
||||
# ( $e:expr, $t:ident ) => {
|
||||
# $e.downcast_ref::<ChainError<$t>>()
|
||||
# };
|
||||
# ( $e:expr, $t:path ) => {
|
||||
# $e.downcast_ref::<ChainError<$t>>()
|
||||
# };
|
||||
# }
|
||||
#
|
||||
# #[macro_export]
|
||||
# macro_rules! try_cherr_mut {
|
||||
# ( $e:expr, $t:ident ) => {
|
||||
# $e.downcast_mut::<ChainError<$t>>()
|
||||
# };
|
||||
# ( $e:expr, $t:path ) => {
|
||||
# $e.downcast_mut::<ChainError<$t>>()
|
||||
# };
|
||||
# }
|
||||
# }
|
||||
</code></pre></pre>
|
||||
|
||||
|
@ -496,6 +996,10 @@ fn main() -> Result<(), Box<Error>> {
|
|||
|
||||
|
||||
|
||||
<a rel="next" href="end.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
|
||||
<div style="clear: both"></div>
|
||||
</nav>
|
||||
|
@ -510,6 +1014,10 @@ fn main() -> Result<(), Box<Error>> {
|
|||
|
||||
|
||||
|
||||
<a href="end.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
|
@ -519,12 +1027,6 @@ fn main() -> Result<(), Box<Error>> {
|
|||
|
||||
|
||||
|
||||
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
|
||||
|
||||
|
||||
|
||||
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue