问题描述
我正在尝试学习 Rust 并决定编写一个将十六进制字符串转换为 u64 的程序.
I am trying to learn Rust and decided to write a program that converts a hex string into a u64.
目前,我已将字符串解析为一个 u8 值向量,每个值代表四位(或半字节").我写了下面的代码来获取一个 Vec
并返回一个对应的 u64
.它有效(就我的测试显示而言),但我不确定在 Rust 中这样做是否合适".
Currently, I have parsed the string into a vector of u8 values, each representing four bits (or "nibble"). I wrote the following code to take a Vec<u8>
and return a corresponding u64
. It works (as far as my testing shows), but I am not sure if it is the "appropriate" way in Rust to go about doing this.
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 suppose the main issue I don't know how else to cast a u8
to a u64
value. Could you comment on ways to improve or write the code in a more idiomatic, Rust-like style?
我已经尝试了以下(不成功的)不安全块的替代方法:
I have tried the following (unsuccessful) alternatives to the unsafe block:
Or'ing with i
作为 u64
:
Or'ing with i
as a 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;
推荐答案
您的问题很简单:for i in values
,其中 values
的类型为 &Vec
,遍历每个值的引用;也就是说,i
是 &u8
类型.Oring 和 add 之类的引用是没有意义的;您需要取消引用它,获取底层 u8
.最简单的方法是将其写入 for
循环的模式(对于 for
语法是 for PATTERN in EXPRESSION
,请参阅文档如果需要,请查看模式以获得更多解释;对于这个简单的情况,for &x in y { ... }
基本上意味着 for x in y { let x = *x; ... }
):
Your issue is a simple one: for i in values
, where values
is of type &Vec<u8>
, iterates over references to each value; that is, i
is of type &u8
. Oring and adding and such with references doesn’t make sense; you need to dereference it, getting the underlying u8
. The easiest way of doing this is writing it into the for
loop’s pattern (for the for
grammar is for PATTERN in EXPRESSION
, refer to the documentation on patterns for more explanation if you need it; for this simple case, for &x in y { … }
basically means 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
折叠整个循环形式,如下所示:
The whole form of a loop can be collapsed using Iterator.fold
, too, like this:
fn convert_nibbles_to_u64(values: &[u8]) -> u64 {
values.iter().fold(0, |x, &i| x << 4 | i as u64)
}
这篇关于将半字节转换为 u64 的最合适方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!