Rust 1.26.0 and higher
The :x? The debug with hexadecimal integer formatter can be used:
let data = b"hello"; println!("{:x?}", data); println!("{:X?}", data);
[68, 65, 6c, 6c, 6f] [68, 65, 6C, 6C, 6F]
It can also be combined with the pretty modifier:
let data = b"hello"; println!("{:#x?}", data); println!("{:#X?}", data);
[ 0x68, 0x65, 0x6c, 0x6c, 0x6f ] [ 0x68, 0x65, 0x6C, 0x6C, 0x6F ]
If you need more control or support for older versions of Rust, read on.
Rust 1.0 and higher
use std::fmt::Write; fn main() { let mut s = String::new(); for &byte in "Hello".as_bytes() { write!(&mut s, "{:X} ", byte).expect("Unable to write"); } println!("{}", s); }
This can be imagined by implementing one of the formatting features ( fmt::Debug , fmt::Display , fmt::LowerHex , fmt::UpperHex , etc.) in the structure and having a small constructor:
use std::fmt; struct HexSlice<'a>(&'a [u8]); impl<'a> HexSlice<'a> { fn new<T>(data: &'a T) -> HexSlice<'a> where T: ?Sized + AsRef<[u8]> + 'a { HexSlice(data.as_ref()) } } // You can even choose to implement multiple traits, like Lower and UpperHex impl<'a> fmt::Display for HexSlice<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for byte in self.0 { // Decide if you want to pad out the value here write!(f, "{:X} ", byte)?; } Ok(()) } } fn main() { // To get a 'String' let s = format!("{}", HexSlice::new("Hello")); // Or print it directly println!("{}", HexSlice::new("world")); // Works with HexSlice::new("Hello"); // string slices (&str) HexSlice::new(b"Hello"); // byte slices (&[u8]) HexSlice::new(&"World".to_string()); // References to String HexSlice::new(&vec![0x00, 0x01]); // References to Vec<u8> }