#[macro_export]
macro_rules! track {
($target:expr) => {
{
use $crate::Trackable;
let mut target = $target;
target.track(|| {
let location = $crate::Location::new(
module_path!(), file!(), line!(), String::new());
From::from(location)
});
target
}
};
($target:expr, $($format_arg:tt)+) => {
{
use $crate::Trackable;
let mut target = $target;
target.track(|| {
let message = format!($($format_arg)+);
let location = $crate::Location::new(module_path!(), file!(), line!(), message);
From::from(location)
});
target
}
};
}
#[macro_export]
macro_rules! track_assert {
($cond:expr, $error_kind:expr) => {
track_assert!($cond, $error_kind, "assertion failed: {}", stringify!($cond));
};
($cond:expr, $error_kind:expr, $($format_arg:tt)+) => {
if ! $cond {
track_panic!($error_kind, $($format_arg)+);
}
};
}
#[macro_export]
macro_rules! track_assert_eq {
($left:expr, $right:expr, $error_kind:expr) => {
{
let ref left = $left;
let ref right = $right;
track_assert!(left == right, $error_kind,
"assertion failed: `(left == right)` (left: `{:?}`, right: `{:?}`)",
left, right);
}
};
($left:expr, $right:expr, $error_kind:expr, $fmt:expr) => {
track_assert_eq!($left, $right, $error_kind, $fmt,);
};
($left:expr, $right:expr, $error_kind:expr, $fmt:expr, $($arg:tt)*) => {
{
let ref left = $left;
let ref right = $right;
track_assert!(
left == right, $error_kind,
concat!("assertion failed: `(left == right)` (left: `{:?}`, right: `{:?}`): ",
$fmt),
left, right, $($arg)*);
}
};
}
#[macro_export]
macro_rules! track_assert_ne {
($left:expr, $right:expr, $error_kind:expr) => {
{
let ref left = $left;
let ref right = $right;
track_assert!(left != right, $error_kind,
"assertion failed: `(left != right)` (left: `{:?}`, right: `{:?}`)",
left, right);
}
};
($left:expr, $right:expr, $error_kind:expr, $fmt:expr) => {
track_assert_ne!($left, $right, $error_kind, $fmt,);
};
($left:expr, $right:expr, $error_kind:expr, $fmt:expr, $($arg:tt)*) => {
{
let ref left = $left;
let ref right = $right;
track_assert!(
left != right, $error_kind,
concat!("assertion failed: `(left != right)` (left: `{:?}`, right: `{:?}`): ",
$fmt),
left, right, $($arg)*);
}
};
}
#[macro_export]
macro_rules! track_panic {
($error:expr) => {
{
let e = $crate::error::TrackableError::from($error);
let e = track!(e);
return Err(From::from(e));
}
};
($error_kind:expr, $($format_arg:tt)+) => {
{
use $crate::error::ErrorKindExt;
let message = format!($($format_arg)+);
track_panic!($error_kind.cause(message));
}
};
}
#[macro_export]
macro_rules! track_try_unwrap {
($expr:expr) => {
match track!($expr) {
Err(e) => { panic!("\nEXPRESSION: {}\nERROR: {}\n", stringify!($expr), e); }
Ok(v) => { v }
}
};
($expr:expr, $($format_arg:tt)*) => {
match track!($expr, $($format_arg)*) {
Err(e) => { panic!("\nEXPRESSION: {}\nERROR: {}\n", stringify!($expr), e); }
Ok(v) => { v }
}
};
}
#[macro_export]
macro_rules! derive_traits_for_trackable_error_newtype {
($error:ident, $kind:ty) => {
impl ::std::ops::Deref for $error {
type Target = $crate::error::TrackableError<$kind>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl ::std::fmt::Display for $error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
impl ::std::error::Error for $error {
fn description(&self) -> &str {
self.0.description()
}
fn cause(&self) -> Option<&::std::error::Error> {
self.0.cause()
}
}
impl $crate::Trackable for $error {
type Event = $crate::error::Event;
fn assign_tracking_number(&mut self) {
self.0.assign_tracking_number();
}
fn tracking_number(&self) -> Option<$crate::TrackingNumber> {
self.0.tracking_number()
}
fn enable_tracking(self) -> Self
where Self: Sized
{
From::from(self.0.enable_tracking())
}
fn disable_tracking(self) -> Self
where Self: Sized
{
From::from(self.0.disable_tracking())
}
fn history(&self) -> Option<&$crate::History<Self::Event>> {
self.0.history()
}
fn history_mut(&mut self) -> Option<&mut $crate::History<Self::Event>> {
self.0.history_mut()
}
}
impl From<$crate::error::TrackableError<$kind>> for $error {
fn from(f: $crate::error::TrackableError<$kind>) -> Self {
$error(f)
}
}
impl From<$error> for $crate::error::TrackableError<$kind> {
fn from(f: $error) -> Self {
f.0
}
}
impl From<$kind> for $error {
fn from(f: $kind) -> Self {
use $crate::error::ErrorKindExt;
f.error().into()
}
}
}
}
#[cfg(test)]
mod test {
use error::Failure;
#[test]
fn track_try_works() {
fn foo(bar: Result<(), Failure>) -> Result<(), Failure> {
struct Baz {
qux: usize,
}
let baz = Baz { qux: 0 };
track!(bar.clone())?;
track!(bar.clone(), "hello")?;
track!(bar.clone(), "baz.qux={}", baz.qux)?;
Ok(())
}
assert!(foo(Ok(())).is_ok());
}
}