custom_print/macros/
dbgwrite.rs

1/// Prints and returns the value of a given expression for quick and dirty debugging
2/// with the specified write macro, writer, format and error-handling policy.
3///
4/// The implementation of the `dbgwrite` macro is based on [`std::dbg`] macro implementation,
5/// but the exact output printed by [`std::dbg`]
6/// should not be relied upon and is subject to future changes.
7///
8/// If the `try` policy is used, it propagates write error and
9/// returns values wrapper into `Result`.
10///
11/// # Panics
12///
13/// The macro panics if writing fails and the `expect` policy is used.
14///
15/// [`std::dbg`]: https://doc.rust-lang.org/std/macro.dbg.html
16///
17/// # Examples
18///
19/// ```rust
20/// use core::fmt::Write;
21/// let mut string = String::new();
22///
23/// assert_eq!(custom_print::dbgwrite!(writeln, &mut string, expect, ":?", "first"), ("first"));
24/// assert!(string.contains("\"first\""));
25/// assert_eq!(custom_print::dbgwrite!(writeln, &mut string, try, ":?", "second"), Ok(("second")));
26/// assert!(string.contains("\"second\""));
27/// ```
28#[macro_export]
29macro_rules! dbgwrite {
30    ( $macro:path, $writer:expr, expect, $format:literal $(, $($args:tt)+)? ) => {
31        $crate::_dbgwrite_impl!( $macro, $writer, $format $(, $($args)+)? )
32    };
33    ( $macro:path, $writer:expr, try, $format:literal $(, $($args:tt)+)? ) => {
34        $crate::_try_dbgwrite_impl!( $macro, $writer, $format $(, $($args)+)? )
35    };
36}
37
38#[doc(hidden)]
39#[macro_export]
40macro_rules! _dbgwrite_impl {
41    ( $macro:path, $writer:expr, $format:literal ) => {
42        $crate::write!(
43            $macro, $writer, expect, "[{}:{}]", ::core::file!(), ::core::line!()
44        );
45    };
46    ( $macro:path, $writer:expr, $format:literal, $val:expr $(,)? ) => {
47        // Use of `match` here is intentional because it affects the lifetimes
48        // of temporaries - https://stackoverflow.com/a/48732525/1063961
49        match $val {
50            tmp => {
51                $crate::write!(
52                    $macro, $writer, expect,
53                    ::core::concat!("[{}:{}] {} = {", $format, "}"),
54                    ::core::file!(), ::core::line!(), ::core::stringify!($val), &tmp
55                );
56                (tmp)
57            }
58        }
59    };
60    ( $macro:path, $writer:expr, $format:literal, $($val:expr),+ $(,)? ) => {
61        ($(
62            match $val {
63                tmp => {
64                    $crate::write!(
65                        $macro, $writer, expect,
66                        ::core::concat!("[{}:{}] {} = {", $format, "}"),
67                        ::core::file!(), ::core::line!(), ::core::stringify!($val), &tmp
68                    );
69                    tmp
70                }
71            }
72        ),+,)
73    };
74}
75
76#[doc(hidden)]
77#[macro_export]
78macro_rules! _try_dbgwrite_impl {
79    ( $macro:path, $writer:expr, $format:literal ) => {
80        $crate::write!(
81            $macro, $writer, try, "[{}:{}]", ::core::file!(), ::core::line!()
82        ).map(|_| ());
83    };
84    ( $macro:path, $writer:expr, $format:literal, $val:expr $(,)? ) => {
85        // Use of `match` here is intentional because it affects the lifetimes
86        // of temporaries - https://stackoverflow.com/a/48732525/1063961
87        match $val {
88            tmp => {
89                $crate::write!(
90                    $macro, $writer, try,
91                    ::core::concat!("[{}:{}] {} = {", $format, "}"),
92                    ::core::file!(), ::core::line!(), ::core::stringify!($val), &tmp
93                ).map(|_| tmp)
94            }
95        }
96    };
97    ( $macro:path, $writer:expr, $format:literal, $($val:expr),+ $(,)? ) => {
98        (|| {
99            Ok(($(
100                match $val {
101                    tmp => {
102                        match $crate::write!(
103                            $macro, $writer, try,
104                            ::core::concat!("[{}:{}] {} = {", $format, "}"),
105                            ::core::file!(), ::core::line!(), ::core::stringify!($val), &tmp
106                        ) {
107                            Ok(_) => tmp,
108                            Err(err) => return Err(err),
109                        }
110                    }
111                }
112            ),+,))
113        })()
114    };
115}