#[macro_export]
macro_rules! trace {
() => { println!(trace!(@line)); };
(#) => { println!(trace!(@line)); };
(#$label:literal) => {
println!("{:?}", $label);
};
($label:literal) => {
println!("{}", $label);
};
(#$($IT:expr),* $(,)?) => {
println!(
trace!(@#fmt $($IT),*),
$(&$IT),*
);
};
($($IT:expr),* $(,)?) => {
println!(
trace!(@fmt $($IT),*),
$(&$IT),*
);
};
(@line) => {
concat!(
file!(), ":", line!(),
)
};
(@#fmt $($IT:expr),*) => {
concat!(
trace!(@stringify $($IT,)*),
":",
$(trace!(@#fmtcode $IT)),*
)
};
(@fmt $($IT:expr),*) => {
concat!(
trace!(@stringify $($IT,)*),
":",
$(trace!(@fmtcode $IT)),*
)
};
(@#fmtcode $_:expr) => {
" {:#?}"
};
(@fmtcode $_:expr) => {
" {:?}"
};
(@stringify $HEAD:expr, $($IT:expr,)*) => {
concat!(
stringify!($HEAD),
$(
", ",
stringify!($IT),
)*
)
};
}
#[cfg(test)]
mod tests {
#[test]
fn no_move() {
let string = format!("hey");
trace!(string, 9);
trace!(string, string);
trace!(
string,
string,
string,
);
}
#[test]
fn single_eval_per_arg() {
let mut n = 0;
fn incr(i: &mut usize) { *i += 1; }
trace!(
"check that each argument",
"is only evaluated",
"once",
incr(&mut n),
);
trace!(n);
assert_eq!(n, 1);
}
#[test]
fn empty() {
trace!();
}
#[test]
fn single() {
let hello = "hello";
trace!(hello);
}
#[test]
fn literal() {
trace!("hi");
trace!(0xED);
}
#[test]
fn multi() {
trace!("hello", "world!");
}
#[test]
fn the_docs() {
let a = 3;
let b = 4;
let c = 5;
trace!(a, b, c);
trace!(a * a + b * b, c * c);
trace!();
#[derive(Debug, Default)]
struct Coords {
x: f32,
y: f32,
}
trace!(#);
trace!(#"hello");
let zero = Coords::default();
trace!(#zero);
}
}