如何将字节片段 (&[u8]) 的缓冲区转换为整数?
How can I convert a buffer of a slice of bytes (&[u8]) to an 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);
}
这些方法只处理固定长度的数组,以避免在数据不足时处理错误。如果您有切片,则需要 convert it into an array.
另请参阅:
- How to get a slice as an array in Rust?
我想在这里给出这个答案以提交以下附加细节:
- 将 slice 转换为整数的工作代码片段(两种方法)。
no_std
环境中的工作解决方案。
- 为从搜索引擎来到这里的人们把一切都放在一个地方。
没有外部包装箱,以下方法适用于从 切片 转换为整数,即使对于从 no_std
开始的构建生锈 1.32:
方法一(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_bytes, from_be_bytes, and from_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);
结果
在这两种情况下,整数都将等于 0x03040506
。
此自定义 serialize_deserialize_u8_i32 库将安全地在 u8 数组和 i32 数组之间来回转换,即序列化函数将获取所有 u8 值并将它们打包为 i32 值,反序列化函数将获取此库的自定义 i32 值并将它们转换回您开始使用的原始 u8 值。
这是为特定目的而构建的,但它可能会派上用场用于其他用途;取决于您是否 want/need 一个像这样的 fast/custom 转换器。
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()
方法 returns 两个切片的元组:一个从索引 0 到指定索引,另一个从指定索引到结尾。因此,通过使用 .0
访问 .split_at(8)
返回的元组的第一个成员,它确保只有前 8 个字节被传递给 u64::to_ne_bytes()
,丢弃剩余部分。然后,当然,它会在那个 .0
元组成员上调用 try_into
方法,并且 .unwrap()
因为 split_at
会为您执行所有自定义恐慌。
我正在从文件中读取原始数据,我想将其转换为整数:
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);
}
这些方法只处理固定长度的数组,以避免在数据不足时处理错误。如果您有切片,则需要 convert it into an array.
另请参阅:
- How to get a slice as an array in Rust?
我想在这里给出这个答案以提交以下附加细节:
- 将 slice 转换为整数的工作代码片段(两种方法)。
no_std
环境中的工作解决方案。- 为从搜索引擎来到这里的人们把一切都放在一个地方。
没有外部包装箱,以下方法适用于从 切片 转换为整数,即使对于从 no_std
开始的构建生锈 1.32:
方法一(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_bytes, from_be_bytes, and from_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);
结果
在这两种情况下,整数都将等于 0x03040506
。
此自定义 serialize_deserialize_u8_i32 库将安全地在 u8 数组和 i32 数组之间来回转换,即序列化函数将获取所有 u8 值并将它们打包为 i32 值,反序列化函数将获取此库的自定义 i32 值并将它们转换回您开始使用的原始 u8 值。
这是为特定目的而构建的,但它可能会派上用场用于其他用途;取决于您是否 want/need 一个像这样的 fast/custom 转换器。
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()
方法 returns 两个切片的元组:一个从索引 0 到指定索引,另一个从指定索引到结尾。因此,通过使用 .0
访问 .split_at(8)
返回的元组的第一个成员,它确保只有前 8 个字节被传递给 u64::to_ne_bytes()
,丢弃剩余部分。然后,当然,它会在那个 .0
元组成员上调用 try_into
方法,并且 .unwrap()
因为 split_at
会为您执行所有自定义恐慌。