Rust从&[u8] bytes中读取任意类型的整数(如i32, u32等多种类型)

9 篇文章 0 订阅
6 篇文章 0 订阅

我想实现一个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,成功读取!

完毕!

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值