繁体   English   中英

如何将一片字节 (&[u8]) 的缓冲区转换为 integer?

[英]How can I convert a buffer of a slice of bytes (&[u8]) to an integer?

我正在从文件中读取原始数据,我想将其转换为 integer:

fn main() {
    let buf: &[u8] = &[0, 0, 0, 1];
    let num = slice_to_i8(buf);
    println!("1 == {}", num);
}

pub fn slice_to_i8(buf: &[u8]) -> i32 {
    unimplemented!("what should I do here?")
}

我会在 C 做演员表,但我在 Rust 做什么?

我建议使用byteorder crate (它也适用于非标准环境):

use byteorder::{BigEndian, ReadBytesExt}; // 1.2.7

fn main() {
    let mut buf: &[u8] = &[0, 0, 0, 1];
    let num = buf.read_u32::<BigEndian>().unwrap();

    assert_eq!(1, num);
}

这会处理奇怪大小的切片并自动推进缓冲区,以便您可以读取多个值。

从 Rust 1.32 开始,您还可以对整数使用from_le_bytes / from_be_bytes / from_ne_bytes固有方法:

fn main() {
    let buf = [0, 0, 0, 1];
    let num = u32::from_be_bytes(buf);

    assert_eq!(1, num);
}

这些方法只处理固定长度的数组,以避免在数据不足时处理错误。 如果您有切片,则需要将其转换为数组

也可以看看:

我想在这里给出这个答案以提交以下附加细节:

  1. 切片转换为整数的工作代码片段(两种方法)。
  2. no_std环境中的有效解决方案。
  3. 将所有内容都放在一个地方,供人们从搜索引擎到达这里。

在没有外部 crate 的情况下,即使对于从 Rust 1.32 开始的no_std构建,以下方法也适用于从切片转换为整数:

方法一( try_into + from_be_bytes

use core::convert::TryInto;

let src = [1, 2, 3, 4, 5, 6, 7];

// 0x03040506
u32::from_be_bytes(src[2..6].try_into().unwrap());

use core::conver::TryInto用于no_std构建。 使用标准板条箱的方法如下: use std::convert::TryInto; .

(关于字节序,它已经得到了回答,但让我把它放在一个地方: from_le_bytesfrom_be_bytesfrom_ne_bytes - 根据整数在内存中的表示方式来使用它们)。

方法二( clone_from_slice + from_be_bytes

let src = [1, 2, 3, 4, 5, 6, 7];
let mut dst = [0u8; 4];

dst.clone_from_slice(&src[2..6]);

// 0x03040506
u32::from_be_bytes(dst);

结果

在这两种情况下 integer 将等于0x03040506

这个自定义的 serialize_deserialize_u8_i32 库将安全地在 u8 数组和 i32 数组之间来回转换,即序列化函数将获取所有 u8 值并将它们打包成 i32 值,反序列化函数将获取这个库的自定义 i32 值并将它们转换回您开始使用的原始 u8 值。

这是为特定目的而构建的,但它可能会在其他用途​​中派上用场; 取决于您是否想要/需要这样的快速/自定义转换器。

https://github.com/second-state/serialize_deserialize_u8_i32

这是我的实现(针对不同的用例),它丢弃超过 8 个的任何额外字节(因此如果不准确则不需要恐慌):

pub fn u64_from_slice(slice: &[u8]) -> u64 {
    u64::from_ne_bytes(slice.split_at(8).0.try_into().unwrap())
}

split_at()方法返回一个包含两个切片的元组:一个从索引 0 到指定索引,另一个从指定索引到结尾。 因此,通过使用.0访问.split_at(8)返回的元组的第一个成员,它确保只有前 8 个字节被传递给u64::to_ne_bytes() ,丢弃剩余部分。 然后,当然,它会调用该.0元组成员的try_into方法和.unwrap() ,因为split_at会为您执行所有自定义恐慌。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM