取编译时已知的特定长度的切片 [英] Take slice of certain length known at compile time

查看:37
本文介绍了取编译时已知的特定长度的切片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这段代码中:

fn unpack_u32(data: &[u8]) -> u32 {
    assert_eq!(data.len(), 4);
    let res = data[0] as u32 |
    (data[1] as u32) << 8 |
    (data[2] as u32) << 16 |
        (data[3] as u32) << 24;
    res
}

fn main() {
    let v = vec![0_u8, 1_u8, 2_u8, 3_u8, 4_u8, 5_u8, 6_u8, 7_u8, 8_u8];
    println!("res: {:X}", unpack_u32(&v[1..5]));    
}

函数 unpack_u32 只接受长度为 4 的切片.有没有办法用编译时检查替换运行时检查 assert_eq?

the function unpack_u32 accepts only slices of length 4. Is there any way to replace the runtime check assert_eq with a compile time check?

推荐答案

是的,有点.第一步很简单:将参数类型从 &[u8] 更改为 [u8;4]:

Yes, kind of. The first step is easy: change the argument type from &[u8] to [u8; 4]:

fn unpack_u32(data: [u8; 4]) -> u32 { ... }

但是将切片(如 &v[1..5])转换为 [u8; 类型的对象;4] 很难.您当然可以通过指定所有元素来创建这样的数组,如下所示:

But transforming a slice (like &v[1..5]) into an object of type [u8; 4] is hard. You can of course create such an array simply by specifying all elements, like so:

unpack_u32([v[1], v[2], v[3], v[4]]);

但这打起来相当难看,而且不能很好地适应数组大小.所以问题是如何将切片作为Rust 中的数组?".我使用了 Matthieu M. 对上述问题的回答的略微修改版本(游乐场):

But this is rather ugly to type and doesn't scale well with array size. So the question is "How to get a slice as an array in Rust?". I used a slightly modified version of Matthieu M.'s answer to said question (playground):

fn unpack_u32(data: [u8; 4]) -> u32 {
    // as before without assert
}

use std::convert::AsMut;

fn clone_into_array<A, T>(slice: &[T]) -> A
    where A: Default + AsMut<[T]>,
          T: Clone
{
    assert_eq!(slice.len(), std::mem::size_of::<A>()/std::mem::size_of::<T>());

    let mut a = Default::default();
    <A as AsMut<[T]>>::as_mut(&mut a).clone_from_slice(slice);
    a
}

fn main() {
    let v = vec![0_u8, 1, 2, 3, 4, 5, 6, 7, 8];
    println!("res: {:X}", unpack_u32(clone_into_array(&v[1..5])));    
}

如您所见,仍然存在 assert 并且因此存在运行时失败的可能性.Rust 编译器无法知道 v[1..5] 有 4 个元素,因为 1..5 只是 Range 这只是编译器知道的一种类型没什么特别的.

As you can see, there is still an assert and thus the possibility of runtime failure. The Rust compiler isn't able to know that v[1..5] is 4 elements long, because 1..5 is just syntactic sugar for Range which is just a type the compiler knows nothing special about.

这篇关于取编译时已知的特定长度的切片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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