将半字节转换为 u64 的最合适方法是什么? [英] What is the most appropriate way to convert nibbles to a u64?

查看:84
本文介绍了将半字节转换为 u64 的最合适方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习 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 的最合适方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆