2

I am looking to create a macro that will display a type of number in hex along leading zeros equal to its size. For example, hex!(2u8) will print $02 (leading zero) and hex!(2u16) will print $0002 (16bit leading zeros)

This is what I have now, but it only works for 8bit numbers. It will display numbers larger than 8bit, but it won't display leading zeros equal to the size. I need a way to substitute the size of the integer in for 2 in ${:02X} but the print!() macro requires a string literal.

macro_rules! hex {
    ($val:expr) => {{
        println!("${:02X}", $val);
    }}
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
user2936448
  • 335
  • 4
  • 16

2 Answers2

5

Instead of directly printing it somewhere I suggest using a wrapper structure which will format the content according to your needs:

use std::fmt;

#[derive(Debug)]
pub struct UpperHexLeadingZeroes<T>(pub T);
impl<T: fmt::UpperHex> fmt::Display for UpperHexLeadingZeroes<T> {
    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
        use std::mem::size_of;
        let width = size_of::<T>() * 2; // 2 nibbles per byte
        write!(w, "${:0width$X}", self.0, width = width)
    }
}

Use it like this:

fn main() {
    println!("{}", UpperHexLeadingZeroes(2u8));
    println!("{}", UpperHexLeadingZeroes(2u16));
    println!("{}", UpperHexLeadingZeroes(2u32));
    println!("{}", UpperHexLeadingZeroes(2u64));
}
Stefan
  • 5,304
  • 2
  • 25
  • 44
4

You don't really need a macro for this. With the Formatter's dollar syntax, the width of the printed value can be specified in terms of an expression, as you intend here.

fn hex<T: UpperHex>(e: T) {
    println!("{:01$X}", e, mem::align_of::<T>() * 2);
}

Playground

E_net4
  • 27,810
  • 13
  • 101
  • 139