如何在Rust中将字符串转换为十六进制?

时间:2014-12-15 20:55:34

标签: type-conversion hex rust

我想在Rust中将一串字符(SHA256哈希)转换为十六进制:

extern crate crypto;
extern crate rustc_serialize;

use rustc_serialize::hex::ToHex;
use crypto::digest::Digest;
use crypto::sha2::Sha256;

fn gen_sha256(hashme: &str) -> String {
    let mut sh = Sha256::new();
    sh.input_str(hashme);

    sh.result_str()
}

fn main() {
    let hash = gen_sha256("example");

    hash.to_hex()
}

编译器说:

error[E0599]: no method named `to_hex` found for type `std::string::String` in the current scope
  --> src/main.rs:18:10
   |
18 |     hash.to_hex()
   |          ^^^^^^

我可以看到这是真的;它看起来像it's only implemented for [u8]

我该怎么办?在Rust中没有实现从字符串转换为十六进制的方法吗?

我的Cargo.toml依赖项:

[dependencies]
rust-crypto = "0.2.36"
rustc-serialize = "0.3.24"

编辑我刚刚从rust-crypto库中意识到字符串是已经的十六进制格式。 D'哦。

4 个答案:

答案 0 :(得分:13)

我会在这里发表意见,并建议hash的解决方案属于Vec<u8>类型。


问题在于,虽然您确实可以使用String&[u8]转换为as_bytes,然后使用to_hex,但您首先需要有效String对象开头。

虽然任何String对象都可以转换为&[u8],但反之则不然。 String对象仅用于保存有效的UTF-8编码的Unicode字符串:并非所有字节模式都符合条件。

因此,gen_sha256生成String是不正确的。更正确的类型是Vec<u8>,它实际上可以接受任何字节模式。从那时起,调用to_hex很容易:

hash.as_slice().to_hex()

答案 1 :(得分:5)

ToHex的来源似乎有我正在寻找的解决方案。它包含一个测试:

#[test]
pub fn test_to_hex() {
    assert_eq!("foobar".as_bytes().to_hex(), "666f6f626172");
}

我修改后的代码是:

let hash = gen_sha256("example");

hash.as_bytes().to_hex()

这似乎有效。如果有人有其他答案,我会花一些时间接受这个解决方案。

答案 2 :(得分:3)

可以使用如下函数生成十六进制表示:

pub fn hex_push(buf: &mut String, blob: &[u8]) {
    for ch in blob {
        fn hex_from_digit(num: u8) -> char {
            if num < 10 {
                (b'0' + num) as char
            } else {
                (b'A' + num - 10) as char
            }
        }
        buf.push(hex_from_digit(ch / 16));
        buf.push(hex_from_digit(ch % 16));
    }
}

这比generic radix formatting implemented currently in the language更有效。

这是benchmark

test bench_specialized_hex_push   ... bench:          12 ns/iter (+/- 0) = 250 MB/s
test bench_specialized_fomat      ... bench:          42 ns/iter (+/- 12) = 71 MB/s
test bench_specialized_format     ... bench:          47 ns/iter (+/- 2) = 63 MB/s
test bench_specialized_hex_string ... bench:          76 ns/iter (+/- 9) = 39 MB/s
test bench_to_hex                 ... bench:          82 ns/iter (+/- 12) = 36 MB/s
test bench_format                 ... bench:          97 ns/iter (+/- 8) = 30 MB/s

答案 3 :(得分:0)

感谢freenode中 ## rust irc频道中的用户j ey。您可以只使用fmt提供的十六进制表示形式,

>> let mut s = String::new();
>> use std::fmt::Write as FmtWrite; // renaming import to avoid collision
>> for b in "hello world".as_bytes() { write!(s, "{:02x}", b); }
()
>> s
"68656c6c6f20776f726c64"
>> 

或者有点傻,

>> "hello world".as_bytes().iter().map(|x| format!("{:02x}", x)).collect::<String>()
"68656c6c6f20776f726c64"