macro_rules! format_args {
($($arg:tt)*) => { ... };
}
Expand description
Constructs parameters for the other string-formatting macros.
§Important note
The other macros in this crate use an inner match
to avoid reevaluating the input arguments several times.
For example, the following println!
call:
use custom_format as cfmt;
use core::fmt;
#[derive(Debug)]
struct Hex(u8);
impl cfmt::runtime::CustomFormat for Hex {
fn fmt(&self, f: &mut fmt::Formatter, _: &str) -> fmt::Result {
write!(f, "{:#02x}", self.0)
}
}
fn call() -> Hex {
Hex(42)
}
cfmt::println!("{0:?}, {res :<x>}", res = call());
is expanded to:
match (&(call())) {
(arg0) => ::std::println!("{0:?}, {1}", arg0, cfmt::runtime::CustomFormatter::new("x", arg0)),
}
This method doesn’t work with the format_args!
macro, since it returns a value of type core::fmt::Arguments
which borrows the temporary values of the match
. Since these temporary values are dropped before returning,
the return value cannot be used at all if the format string contains format specifiers.
For this reason, the format_args!
macro is expanded in another way. The following call:
println!("{}", cfmt::format_args!("{0:?}, {res :<x>}", res = call()));
must be expanded to:
println!("{}", ::core::format_args!("{0:?}, {1}", &(call()), cfmt::runtime::CustomFormatter::new("x", &(call()))));
which reevaluates the input arguments if they are used several times in the format string.
To avoid unnecessary reevaluations, we can store the expression result in a variable beforehand:
let res = call();
println!("{}", cfmt::format_args!("{res:?}, {res :<x>}"));
is expanded to:
println!("{}", ::core::format_args!("{0:?}, {1}", &res, cfmt::runtime::CustomFormatter::new("x", &res)))