Reputation: 433
I have the following integer literal:
let centre: u64 = 0b00000000_00000000_00111100_00111100_00111100_00111100_00000000_00000000;
It represents a chess board, so I think it would be much nicer to format it similar to this:
let centre: u64 = 0b
00000000
00000000
00111100
00111100
00111100
00111100
00000000
00000000;
However, the above example doesn't compile as the newlines get interpreted as whitespaces inside my literal. Is there any way to achieve this?
Upvotes: 4
Views: 337
Reputation: 2324
Solution above works well. But the macro can be simplified a bit:
macro_rules! chessboard {
($($bytes:literal)*) => {{
let mut result: u64 = 0;
let mut offset = 64;
$(
offset -= 8;
result |= ($bytes as u64) << offset;
)*
result
}}
}
}
fn main() {
let centre: u64 = chessboard!(
0b_00000000
0b_00000000
0b_00111100
0b_00111100
0b_00111100
0b_00111100
0b_00000000
0b_00000000);
println!("{:#b}", centre);
}
Upvotes: 0
Reputation: 65702
There's no way to concatenate tokens into a new token (as you could do with ##
in the C preprocessor) with the macros in the standard library (as of Rust 1.22).
However, I came up with the following macro. It repeats 0b_
on each line, but at least you can clearly see the pattern from the zeroes and ones. The shifts and ORs are evaluated at compile time, so there's no runtime penalty to this solution compared to a plain literal.
macro_rules! chessboard {
($line0:tt $line1:tt $line2:tt $line3:tt $line4:tt $line5:tt $line6:tt $line7:tt) => {
($line0 << 56) |
($line1 << 48) |
($line2 << 40) |
($line3 << 32) |
($line4 << 24) |
($line5 << 16) |
($line6 << 8) |
($line7 << 0)
}
}
fn main() {
let centre: u64 = chessboard!(
0b_00000000
0b_00000000
0b_00111100
0b_00111100
0b_00111100
0b_00111100
0b_00000000
0b_00000000);
println!("{:#b}", centre);
}
Upvotes: 5