1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright Ⓒ 2019 David Kellum
//
// These _-v_ macros were co-developed with
// https://github.com/rust-lang-nursery/log/pull/316 (by the same author)
//
// All original _log_ source is offered under the same Apache 2.0 or MIT
// licenses, and is:
// Copyright Ⓒ 2015 The Rust Project Developers

/// Log an expression and its value at any specified level.
///
/// Logs with the optional or default (module path of use) target, specified
/// `Level`, optional prefix, and optional or default (`"{:?}"`) value format
/// string, and a single expression. The expression argument is evaluated
/// exactly once, regardless of if the logging level is enabled, and its
/// value is returned from the macro. This is normally only used through the
/// _-v_ macros like `debugv!` or `tracev!`.
///
/// Note that the value is moved and then returned. If the type does not
/// implement `Copy`, ownership may be retained by borrowing by reference
/// e.g. `debugv!(&expr)`.
///
/// # Examples
///
/// ```rust
/// use tao_log::*;
///
/// #[derive(Debug)]
/// struct Point { x: f32, y: f32 }
///
/// fn circle(center: &Point, radius: f32) { /*...*/ }
///
/// # fn main() {
/// let center = Point { x: 3.234, y: -1.223 };
///
/// circle(logv!(log::Level::Trace, &center), 7.3);
/// //     ^-- trace level message: "&center → Point { x: 3.234, y: -1.223 }"
/// circle(tracev!(&center), 8.0);
/// //     ^-- trace level message: "&center → Point { x: 3.234, y: -1.223 }"
/// # }
/// ```
#[macro_export]
macro_rules! logv {
    (target: $target:expr, $lvl:expr, $($arg:tt)+) => (
        $crate::__tao_logv!($lvl, target: $target, $($arg)+)
    );
    ($lvl:expr, $($arg:tt)+) => (
        $crate::__tao_logv!($lvl, target: module_path!(), $($arg)+)
    );
}

/// Log an expression at the error level, returning its value.
#[macro_export]
macro_rules! errorv {
    ($($arg:tt)+) => ($crate::__tao_logv!($crate::log::Level::Error, $($arg)+))
}

/// Log an expression at the warn level, returning its value.
#[macro_export]
macro_rules! warnv {
    ($($arg:tt)+) => ($crate::__tao_logv!($crate::log::Level::Warn, $($arg)+))
}

/// Log an expression at the info level, returning its value.
#[macro_export]
macro_rules! infov {
    ($($arg:tt)+) => ($crate::__tao_logv!($crate::log::Level::Info, $($arg)+))
}

/// Log an expression at the debug level, returning its value.
#[macro_export]
macro_rules! debugv {
    ($($arg:tt)+) => ($crate::__tao_logv!($crate::log::Level::Debug, $($arg)+))
}

/// Log an expression at the trace level, returning its value.
#[macro_export]
macro_rules! tracev {
    ($($arg:tt)+) => ($crate::__tao_logv!($crate::log::Level::Trace, $($arg)+))
}

// Helper macro for the -v macros, handling the permutations of optional
// parameters. Note: The required level parameter is first here for
// convenience of internal use with variable-args.
#[doc(hidden)]
#[macro_export]
macro_rules! __tao_logv {
    ($lvl:expr, target: $tgt:expr, $pre:expr, $vfmt:expr, $exp:expr) => (
        $crate::__tao_v_eval!($tgt, $lvl, concat!($pre, " {} → ", $vfmt), $exp)
    );
    ($lvl:expr, target: $tgt:expr, $pre:expr, $exp:expr) => (
        $crate::__tao_v_eval!($tgt, $lvl, concat!($pre, " {} → {:?}"), $exp)
    );
    ($lvl:expr, target: $tgt:expr, $exp:expr) => (
        $crate::__tao_v_eval!($tgt, $lvl, "{} → {:?}", $exp)
    );
    ($lvl:expr, $pre:expr, $vfmt:expr, $exp:expr) => (
        $crate::__tao_v_eval!(module_path!(), $lvl, concat!($pre, " {} → ", $vfmt), $exp)
    );
    ($lvl:expr, $pre:expr, $exp:expr) => (
        $crate::__tao_v_eval!(module_path!(), $lvl, concat!($pre, " {} → {:?}"), $exp)
    );
    ($lvl:expr, $exp:expr) => (
        $crate::__tao_v_eval!(module_path!(), $lvl, "{} → {:?}", $exp)
    );
}

// Inner helper macro for __tao_logv. Evaluates expression exactly once, moves
// value and returns it.
#[doc(hidden)]
#[macro_export]
macro_rules! __tao_v_eval {
    ($tgt:expr, $lvl:expr, $fmt:expr, $exp:expr) => (
        match $exp {
            vt => {
                $crate::log!(target: $tgt, $lvl, $fmt, stringify!($exp), &vt);
                vt
            }
        }
    )
}