Skip to content
This repository was archived by the owner on Aug 16, 2021. It is now read-only.

Commit dd30cb4

Browse files
committed
[WIP] Add boxed-error feature.
Fixes #44.
1 parent 659b598 commit dd30cb4

File tree

3 files changed

+98
-17
lines changed

3 files changed

+98
-17
lines changed

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ repository = "https://github.com/brson/error-chain"
1515
license = "MIT/Apache-2.0"
1616

1717
[features]
18-
default = ["backtrace", "example_generated"]
19-
example_generated = []
18+
default = ["backtrace", "example-generated"]
19+
example-generated = []
20+
boxed-error = []
2021

2122
[dependencies]
2223
backtrace = { version = "0.3", optional = true }

src/error_chain.rs

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ macro_rules! error_chain_processed {
2626
}
2727
$( $rest )*
2828
}
29-
/// Convenient wrapper around `std::Result`.
30-
pub type $result_name<T> = ::std::result::Result<T, $error_name>;
29+
result_wrapper!($result_name, $error_name);
3130
};
3231
// Without `Result` wrapper.
3332
(
@@ -70,14 +69,9 @@ macro_rules! error_chain_processed {
7069

7170
impl $crate::ChainedError for $error_name {
7271
type ErrorKind = $error_kind_name;
72+
maybe_boxed_error!();
7373

74-
fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
75-
$error_name {
76-
kind: kind,
77-
state: state,
78-
}
79-
}
80-
74+
impl_chained_error_new!($error_name, $error_kind_name);
8175
impl_extract_backtrace!($error_name
8276
$error_kind_name
8377
$([$link_error_path, $(#[$meta_links])*])*);
@@ -148,6 +142,15 @@ macro_rules! error_chain_processed {
148142
}
149143
}
150144
}
145+
$(#[$meta_links])*
146+
impl From<$link_error_path> for Box<$error_name> {
147+
fn from(e: $link_error_path) -> Self {
148+
Box::new($error_name {
149+
kind: $error_kind_name::$link_variant(e.kind),
150+
state: e.state,
151+
})
152+
}
153+
}
151154
) *
152155

153156
$(
@@ -159,6 +162,14 @@ macro_rules! error_chain_processed {
159162
)
160163
}
161164
}
165+
$(#[$meta_foreign_links])*
166+
impl From<$foreign_link_error_path> for Box<$error_name> {
167+
fn from(e: $foreign_link_error_path) -> Self {
168+
Box::new($error_name::from_kind(
169+
$error_kind_name::$foreign_link_variant(e)
170+
))
171+
}
172+
}
162173
) *
163174

164175
impl From<$error_kind_name> for $error_name {
@@ -360,3 +371,69 @@ macro_rules! impl_extract_backtrace {
360371
$error_kind_name: ident
361372
$([$link_error_path: path, $(#[$meta_links: meta])*])*) => {}
362373
}
374+
375+
#[macro_export]
376+
#[doc(hidden)]
377+
#[cfg(feature = "boxed-error")]
378+
macro_rules! result_wrapper {
379+
($result_name: ident, $error_name: ident) => {
380+
/// Convenient wrapper around `std::Result`.
381+
pub type $result_name<T> = ::std::result::Result<T, Box<$error_name>>;
382+
}
383+
}
384+
385+
#[macro_export]
386+
#[doc(hidden)]
387+
#[cfg(not(feature = "boxed-error"))]
388+
macro_rules! result_wrapper {
389+
($result_name: ident, $error_name: ident) => {
390+
/// Convenient wrapper around `std::Result`.
391+
pub type $result_name<T> = ::std::result::Result<T, $error_name>;
392+
}
393+
}
394+
395+
#[macro_export]
396+
#[doc(hidden)]
397+
#[cfg(feature = "boxed-error")]
398+
macro_rules! maybe_boxed_error {
399+
() => {
400+
type Error = Box<Self>;
401+
}
402+
}
403+
404+
#[macro_export]
405+
#[doc(hidden)]
406+
#[cfg(not(feature = "boxed-error"))]
407+
macro_rules! maybe_boxed_error {
408+
() => {
409+
type Error = Self;
410+
}
411+
}
412+
413+
#[macro_export]
414+
#[doc(hidden)]
415+
#[cfg(feature = "boxed-error")]
416+
macro_rules! impl_chained_error_new {
417+
($error_name: ident, $error_kind_name: ident) => {
418+
fn new(kind: $error_kind_name, state: $crate::State) -> Box<$error_name> {
419+
Box::new($error_name {
420+
kind: kind,
421+
state: state,
422+
})
423+
}
424+
}
425+
}
426+
427+
#[macro_export]
428+
#[doc(hidden)]
429+
#[cfg(not(feature = "boxed-error"))]
430+
macro_rules! impl_chained_error_new {
431+
($error_name: ident, $error_kind_name: ident) => {
432+
fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
433+
$error_name {
434+
kind: kind,
435+
state: state,
436+
}
437+
}
438+
}
439+
}

src/lib.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ pub type Backtrace = ();
269269
mod quick_error;
270270
#[macro_use]
271271
mod error_chain;
272-
#[cfg(feature = "example_generated")]
272+
#[cfg(feature = "example-generated")]
273273
pub mod example_generated;
274274

275275
/// Iterator over the error chain using the `Error::cause()` method.
@@ -304,12 +304,15 @@ pub fn make_backtrace() -> Option<Arc<Backtrace>> {
304304
/// This trait is implemented on all the errors generated by the `error_chain`
305305
/// macro.
306306
pub trait ChainedError: error::Error + Send + 'static {
307+
/// Type used as the second type parameter of `Result`.
308+
type Error;
309+
307310
/// Associated kind type.
308311
type ErrorKind;
309312

310313
/// Creates an error from it's parts.
311314
#[doc(hidden)]
312-
fn new(kind: Self::ErrorKind, state: State) -> Self;
315+
fn new(kind: Self::ErrorKind, state: State) -> Self::Error;
313316

314317
/// Returns the first known backtrace, either from it's State or from one
315318
/// of the errors from `foreign_links`.
@@ -320,18 +323,18 @@ pub trait ChainedError: error::Error + Send + 'static {
320323
}
321324

322325
/// Additionnal methods for `Result`, for easy interaction with this crate.
323-
pub trait ResultExt<T, E, CE: ChainedError> {
326+
pub trait ResultExt<T, E> {
324327
/// If the `Result` is an `Err` then `chain_err` evaluates the closure,
325328
/// which returns *some type that can be converted to `ErrorKind`*, boxes
326329
/// the original error to store as the cause, then returns a new error
327330
/// containing the original error.
328-
fn chain_err<F, EK>(self, callback: F) -> Result<T, CE>
331+
fn chain_err<F, EK, CE: ChainedError>(self, callback: F) -> Result<T, CE::Error>
329332
where F: FnOnce() -> EK,
330333
EK: Into<CE::ErrorKind>;
331334
}
332335

333-
impl<T, E, CE> ResultExt<T, E, CE> for Result<T, E> where CE: ChainedError, E: error::Error + Send + 'static {
334-
fn chain_err<F, EK>(self, callback: F) -> Result<T, CE>
336+
impl<T, E> ResultExt<T, E> for Result<T, E> where E: error::Error + Send + 'static {
337+
fn chain_err<F, EK, CE: ChainedError>(self, callback: F) -> Result<T, CE::Error>
335338
where F: FnOnce() -> EK,
336339
EK: Into<CE::ErrorKind> {
337340
self.map_err(move |e| {

0 commit comments

Comments
 (0)