hex - 以十六进制表示形式显示 u8 切片

标签 hex rust slice

我需要将 &[u8] 转换为十六进制表示。例如 [ A9, 45, FF, 00 ... ]

特征 std::fmt::UpperHex 没有为切片实现(所以我不能使用 std::fmt::format)。 Rust 具有 serialize::hex::ToHex 特性,可将 &[u8] 转换为十六进制字符串,但我需要一个具有单独字节的表示。

我可以自己为 &[u8] 实现特征 UpperHex,但我不确定这是否规范。最规范的方法是什么?

最佳答案

Rust 1.26.0 及更高版本

可以使用 :x? "debug with hexadecimal integers"格式化程序:

let data = b"hello";
// lower case
println!("{:x?}", data);
// upper case
println!("{:X?}", data);

let data = [0x0, 0x1, 0xe, 0xf, 0xff];
// print the leading zero
println!("{:02X?}", data);
// It can be combined with the pretty modifier as well
println!("{:#04X?}", data);

输出:

[68, 65, 6c, 6c, 6f]
[68, 65, 6C, 6C, 6F]
[00, 01, 0E, 0F, FF]
[
    0x00,
    0x01,
    0x0E,
    0x0F,
    0xFF,
]

如果您需要更多控制或需要支持旧版本的 Rust,请继续阅读。

Rust 1.0 及更高版本

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);
}

这可以通过在包装器结构上实现格式特征之一( fmt::Debugfmt::Displayfmt::LowerHexfmt::UpperHex 等)并使用一个小构造函数来实现:

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 choose to implement multiple traits, like Lower and UpperHex
impl fmt::Display for HexSlice<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for byte in self.0 {
            // Decide if you want to pad the value or have spaces inbetween, etc.
            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>
}

您甚至可以更高级地创建一个扩展特征:

trait HexDisplayExt {
    fn hex_display(&self) -> HexSlice<'_>;
}

impl<T> HexDisplayExt for T
where
    T: ?Sized + AsRef<[u8]>,
{
    fn hex_display(&self) -> HexSlice<'_> {
        HexSlice::new(self)
    }
}

fn main() {
    println!("{}", "world".hex_display());
}

关于hex - 以十六进制表示形式显示 u8 切片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27650312/

相关文章:

javascript - 如何获取十六进制元素的背景颜色代码?

rust - 将 '&self' 方法中的闭包添加到结构中的属性

vector - 如何在Vec <T>中将元素从x返回到y?

python - Python 数据框中的多重切片

arrays - []json.Rawmessage 是什么意思

go - 我可以根据条件向创建语句中的 slice 添加项目吗?

c++ - 如何在 C++ 中解析包含 -0x1.0c7474fp+8 形式的十六进制文件?

javascript - 检查字符串是否为 UTF-8 如果是则返回\u+hex 如果不​​是则返回 false

c++ - 使用字符串格式限制十六进制数字的数量

rust - 为什么没有为明确实现的类型实现特征?