Show u8 snippet in hexadecimal notation

I need to convert &[u8] to a hexadecimal representation. For example [ A9, 45, FF, 00 ... ] .

The std::fmt::UpperHex not implemented for slices (therefore, I cannot use std::fmt::format ). Rust has a serialize::hex::ToHex that converts &[u8] to a hexadecimal string, but I need a separate byte representation.

I can implement the UpperHex for &[u8] own, but I'm not sure what it would be. What is the most canonical way to do this?

+13
source share
4 answers

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> } 
+24
source

Since the accepted answer does not work on Rust 1.0 stable, here is my attempt. It should be without allocation and, therefore, fast enough. This is basically a formatter for [u8], but due to consistency rules, we have to wrap [u8] in a self- ByteBuf(&[u8]) type of ByteBuf(&[u8]) to use it:

 struct ByteBuf<'a>(&'a [u8]); impl<'a> std::fmt::LowerHex for ByteBuf<'a> { fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { for byte in self.0 { try!( fmtr.write_fmt(format_args!("{:02x}", byte))); } Ok(()) } } 

Using:

 let buff = [0_u8; 24]; println!("{:x}", ByteBuf(&buff)); 
+5
source

There is a box here: hex-slice .

For instance:

 extern crate hex_slice; use hex_slice::AsHex; fn main() { let foo = vec![0u32, 1, 2 ,3]; println!("{:02x}", foo.as_hex()); } 
+1
source

An executable pattern about the accepted answer with a byte array.

 fn main() { // Template let bytes = [ 177, 147, 134, 198, 163, 82, 51, 22, 41, 118, 161, 105, 142, 86, 191, 146, 250, 11, 152, 10, 58, 75, 238, 24, 21, 46, 68, 18, 3, 112, 162, 50, ]; // String to extend. let mut hex = String::new(); hex.extend(bytes.iter().map(|byte| format!("{:02x}", byte))); // Print it. println!("{:}", hex); } 
0
source

Source: https://habr.com/ru/post/1209891/


All Articles