Though format
has its share of compiler magic, the underlying issue is fundamental to how Rust macros are processed. Macros can’t look at variable values themselves, though they can produce code that does. For example, this shows essentially the same behavior:
macro_rules! digit_to_char {
(0) => { '0' };
(1) => { '1' };
/* ... */
(9) => { '9' };
}
#[test]
fn test(){
// this works
assert_eq!(digit_to_char!(1), '1');
// this doesn't
const X:u8 = 1;
assert_eq!(digit_to_char!(X), '1');
}
error: no rules expected the token `X`
--> src/lib.rs:15:31
|
1 | macro_rules! digit_to_char {
| -------------------------- when calling this macro
...
15 | assert_eq!(digit_to_char!(X), '1');
| ^ no rules expected this token in macro call
(Playground)
format!
is essentially the same, except there’s an infinite number of match arms in its ruleset (one for each valid format string).
I don’t do much string manipulation in Rust, so I’m not familiar with the available crates, unfortunately.