Rust从&[u8] bytes中读取任意类型的整数(如i32, u32等多种类型)-爱代码爱编程
我想实现一个read_integer()
函数,它接收一个&[u8]
切片,然后从切片中读取我们指定类型的整数
就像这样:
let slice = &[254, 255, 0, 0];
let i32_integer = read_integer::<i32>(slice);
let u32_integer = read_integer::<u32>(slice);
...
也就是我给函数传什么类型的整数,他就得从切片里给我返回什么类型的整数。
因为涉及了多种类型,我想到可以使用宏+trait来实现,如下:
use std::convert::TryInto;
pub trait ReadInteger<T> {
fn from_le_bytes(data: &[u8]) -> T;
fn from_be_bytes(data: &[u8]) -> T;
}
macro_rules! impl_read_integer {
($($t:ty),+) => {
$(impl ReadInteger<$t> for $t {
fn from_le_bytes(data: &[u8]) -> $t {
<$t>::from_le_bytes(data.try_into().unwrap())
}
fn from_be_bytes(data: &[u8]) -> $t {
<$t>::from_be_bytes(data.try_into().unwrap())
}
})+
}
}
impl_read_integer!(u8, i16, i32, u32, i64);
遇到大端bytes时使用from_be_bytes
,而小端bytes则是使用from_le_bytes
。
由于使用try_into()
将&[u8]
转换成[u8; std::mem::size_of::<T>()]
,所以需要添加use std::convert::TryInto;
以提供支持!
使用impl_read_integer!
宏来添加对指定类型整数的支持。
trait和宏都准备好了,接下来就是read_integer()
函数:
fn read_integer<T: ReadInteger<T>>(data: &[u8]) -> T {
T::from_le_bytes(&data[..std::mem::size_of::<T>()])
}
由于我只需要处理小端的bytes,所以这样就搞定了,大端bytes直接使用from_be_bytes
即可!
整体效果:
use std::convert::TryInto;
pub trait ReadInteger<T> {
fn from_le_bytes(data: &[u8]) -> T;
fn from_be_bytes(data: &[u8]) -> T;
}
macro_rules! impl_read_integer {
($($t:ty),+) => {
$(impl ReadInteger<$t> for $t {
fn from_le_bytes(data: &[u8]) -> $t {
<$t>::from_le_bytes(data.try_into().unwrap())
}
fn from_be_bytes(data: &[u8]) -> $t {
<$t>::from_be_bytes(data.try_into().unwrap())
}
})+
}
}
impl_read_integer!(u8, i16, i32, u32, i64);
fn read_integer<T: ReadInteger<T>>(data: &[u8]) -> T {
T::from_le_bytes(&data[..std::mem::size_of::<T>()])
}
let slice = &data[254, 255, 0, 0];
let i32_integer = read_integer::<i32>(slice);
let u32_integer = read_integer::<u32>(slice);
println!("{}, {}", i32_integer, u32_integer);
打印结果是65534,成功读取!
完毕!
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接: https://blog.csdn.net/qq_26373925/article/details/111087884