#[macro_export]
macro_rules! error_chain_processed {
(
types {}
$( $rest: tt )*
) => {
error_chain_processed! {
types {
Error, ErrorKind, Result;
}
$( $rest )*
}
};
(
types {
$error_name:ident, $error_kind_name:ident, $result_name:ident;
}
$( $rest: tt )*
) => {
error_chain_processed! {
types {
$error_name, $error_kind_name;
}
$( $rest )*
}
pub type $result_name<T> = ::std::result::Result<T, $error_name>;
};
(
types {
$error_name:ident, $error_kind_name:ident;
}
links {
$( $link_error_path:path, $link_variant:ident $(, #[$meta_links:meta])*; ) *
}
foreign_links {
$( $foreign_link_error_path:path, $foreign_link_variant:ident $(, #[$meta_foreign_links:meta])*; )*
}
errors {
$( $error_chunks:tt ) *
}
) => {
#[derive(Debug)]
pub struct $error_name {
/// The kind of the error.
pub kind: $error_kind_name,
pub state: $crate::State,
}
impl_error!($error_name
$error_kind_name
$([$link_error_path, $(#[$meta_links])*])*);
impl $error_name {
pub fn from_kind(kind: $error_kind_name) -> $error_name {
$error_name {
kind: kind,
state: $crate::State::default(),
}
}
pub fn kind(&self) -> &$error_kind_name {
&self.kind
}
pub fn iter(&self) -> $crate::ErrorChainIter {
$crate::ErrorChainIter(Some(self))
}
}
impl ::std::error::Error for $error_name {
fn description(&self) -> &str {
self.kind.description()
}
fn cause(&self) -> Option<&::std::error::Error> {
match self.state.next_error {
Some(ref c) => Some(&**c),
None => {
match self.kind {
$(
$(#[$meta_foreign_links])*
$error_kind_name::$foreign_link_variant(ref foreign_err) => {
foreign_err.cause()
}
) *
_ => None
}
}
}
}
}
impl ::std::fmt::Display for $error_name {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
::std::fmt::Display::fmt(&self.kind, f)
}
}
$(
$(#[$meta_links])*
impl From<$link_error_path> for $error_name {
fn from(e: $link_error_path) -> Self {
$error_name {
kind: $error_kind_name::$link_variant(e.kind),
state: e.state,
}
}
}
) *
$(
$(#[$meta_foreign_links])*
impl From<$foreign_link_error_path> for $error_name {
fn from(e: $foreign_link_error_path) -> Self {
$error_name::from_kind(
$error_kind_name::$foreign_link_variant(e)
)
}
}
) *
impl From<$error_kind_name> for $error_name {
fn from(e: $error_kind_name) -> Self {
$error_name::from_kind(e)
}
}
impl<'a> From<&'a str> for $error_name {
fn from(s: &'a str) -> Self {
$error_name::from_kind(s.into())
}
}
impl From<String> for $error_name {
fn from(s: String) -> Self {
$error_name::from_kind(s.into())
}
}
impl ::std::ops::Deref for $error_name {
type Target = $error_kind_name;
fn deref(&self) -> &Self::Target {
&self.kind
}
}
quick_error! {
#[derive(Debug)]
pub enum $error_kind_name {
Msg(s: String) {
description(&s)
display("{}", s)
}
$(
$(#[$meta_links])*
$link_variant(e: <$link_error_path as $crate::ChainedError>::ErrorKind) {
description(e.description())
display("{}", e)
}
) *
$(
$(#[$meta_foreign_links])*
$foreign_link_variant(err: $foreign_link_error_path) {
description(::std::error::Error::description(err))
display("{}", err)
}
) *
$($error_chunks)*
}
}
$(
$(#[$meta_links])*
impl From<<$link_error_path as $crate::ChainedError>::ErrorKind> for $error_kind_name {
fn from(e: <$link_error_path as $crate::ChainedError>::ErrorKind) -> Self {
$error_kind_name::$link_variant(e)
}
}
) *
impl<'a> From<&'a str> for $error_kind_name {
fn from(s: &'a str) -> Self {
$error_kind_name::Msg(s.to_string())
}
}
impl From<String> for $error_kind_name {
fn from(s: String) -> Self {
$error_kind_name::Msg(s)
}
}
impl From<$error_name> for $error_kind_name {
fn from(e: $error_name) -> Self {
e.kind
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! error_chain_processing {
(
({}, $b:tt, $c:tt, $d:tt)
types $content:tt
$( $tail:tt )*
) => {
error_chain_processing! {
($content, $b, $c, $d)
$($tail)*
}
};
(
($a:tt, {}, $c:tt, $d:tt)
links $content:tt
$( $tail:tt )*
) => {
error_chain_processing! {
($a, $content, $c, $d)
$($tail)*
}
};
(
($a:tt, $b:tt, {}, $d:tt)
foreign_links $content:tt
$( $tail:tt )*
) => {
error_chain_processing! {
($a, $b, $content, $d)
$($tail)*
}
};
(
($a:tt, $b:tt, $c:tt, {})
errors $content:tt
$( $tail:tt )*
) => {
error_chain_processing! {
($a, $b, $c, $content)
$($tail)*
}
};
( ($a:tt, $b:tt, $c:tt, $d:tt) ) => {
error_chain_processed! {
types $a
links $b
foreign_links $c
errors $d
}
};
}
#[macro_export]
macro_rules! error_chain {
( $( $block_name:ident { $( $block_content:tt )* } )* ) => {
error_chain_processing! {
({}, {}, {}, {})
$($block_name { $( $block_content )* })*
}
};
}
#[macro_export]
#[doc(hidden)]
#[cfg(feature = "backtrace")]
macro_rules! impl_error {
($error_name: ident
$error_kind_name: ident
$([$link_error_path: path, $(#[$meta_links: meta])*])*) => {
impl $error_name {
pub fn backtrace(&self) -> Option<&$crate::Backtrace> {
self.state.backtrace.as_ref().map(|v| &**v)
}
}
impl $crate::ChainedError for $error_name {
type ErrorKind = $error_kind_name;
fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
$error_name {
kind: kind,
state: state,
}
}
fn extract_backtrace(e: &(::std::error::Error + Send + 'static))
-> Option<Option<::std::sync::Arc<$crate::Backtrace>>> {
if let Some(e) = e.downcast_ref::<$error_name>() {
return Some(e.state.backtrace.clone());
}
$(
$( #[$meta_links] )*
{
if let Some(e) = e.downcast_ref::<$link_error_path>() {
return Some(e.state.backtrace.clone());
}
}
) *
None
}
}
}
}
#[macro_export]
#[doc(hidden)]
#[cfg(not(feature = "backtrace"))]
macro_rules! impl_error {
($error_name: ident
$error_kind_name: ident
$([$link_error_path: path, $(#[$meta_links: meta])*])*) => {
impl $crate::ChainedError for $error_name {
type ErrorKind = $error_kind_name;
fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
$error_name {
kind: kind,
state: state,
}
}
}
}
}