我正在尝试学习Rust,并决定编写一个将十六进制字符串转换为u64的程序。
目前,我已将字符串解析为u8值的向量,每个值代表4位(或“半字节”)。我编写了以下代码来获取Vec<u8>
并返回相应的u64
。它可以工作(据我的测试显示),但我不确定在Rust中这是否是“适当”的方式。
fn convert_nibbles_to_u64(values: &Vec<u8>) -> u64 {
// We need to turn this buffer into a u64 now
let mut temp:u64 = 0;
for i in values {
temp = temp << 4;
unsafe {
// We need to unsafely convert a u8 to a u64. Note that
// the host endian-ness will matter here.
use std::mem;
let i_64_buffer = [0u8,0u8,0u8,0u8,0u8,0u8,0u8,i.clone()];
let i_64 = mem::transmute::<[u8; 8], u64>(i_64_buffer);
let i_64_be = u64::from_be(i_64);
temp = temp | i_64_be;
}
}
return temp;
}
我想主要问题我不知道如何将u8
转换为u64
值。您能评论一下以更加惯用的Rust风格改进或编写代码的方法吗?
编辑: 我尝试了以下(不成功)替代不安全的块:
或i
作为u64
:
temp = temp | i as u64;
------
Compiler error:
main.rs:115:23: 115:31 error: non-scalar cast: `&u8` as `u64`
main.rs:115 temp = temp | i as u64;
直接与i
进行联系:
temp = temp | i;
------
Compiler error:
main.rs:115:16: 115:24 error: the trait `core::ops::BitOr<&u8>` is not implemented for the type `u64` [E0277]
main.rs:115 temp = temp | i;
答案 0 :(得分:9)
您的问题很简单:for i in values
,其中values
的类型为&Vec<u8>
,将引用迭代到每个值;也就是说,i
的类型为&u8
。 Oring和添加等参考文献没有意义;您需要取消引用它,获取基础u8
。最简单的方法是将其写入for
循环的模式(for
语法为for PATTERN in EXPRESSION
,如果需要,请参阅模式文档以获得更多解释;为此简单的情况,for &x in y { … }
基本上意味着for x in y { let x = *x; … }
):
fn convert_nibbles_to_u64(values: &[u8]) -> u64 {
let mut out = 0;
for &i in values {
out = out << 4 | i as u64;
}
out
}
循环的整个形式也可以使用Iterator.fold
折叠,如下所示:
fn convert_nibbles_to_u64(values: &[u8]) -> u64 {
values.iter().fold(0, |x, &i| x << 4 | i as u64)
}