借用一个借来的数组的一部分作为借来的数组

时间:2016-11-08 13:53:30

标签: rust

正如标题所示,我将如何做到这一点?

UICollectionView

编译器错误

fn foo(array: &[u32; 10]) -> &[u32; 5] {
    &array[0..5]
}

2 个答案:

答案 0 :(得分:2)

arrayref实现了一个安全的接口来执行此操作,使用宏(当然还有编译时常量切片边界)。

Their readme解释

  

arrayref的目标是在参数必须具有给定大小的情况下,能够有效地使用涉及数组引用而不是切片的API。

let addr: &[u8; 16] = ...;
let mut segments = [0u16; 8];
// array-based API with arrayref
for i in 0 .. 8 {
    segments[i] = read_u16_array(array_ref![addr,2*i,2]);
}
  

这里array_ref![addr,2*i,2]宏允许我们对从2 * i开始的两个字节组成的片段进行数组引用。除了语法(不如切片好),它基本上与切片方法相同。但是,这段代码明确表示在调用者和函数签名中都需要精确的两个字节。

答案 1 :(得分:1)

稳定锈病

仅使用安全的Rust不可能做到这一点。要了解原因,了解如何实现这些类型非常重要。保证数组具有N个初始化元素。它不能变小或变大。在编译时,这些保证允许删除数组的大小方面,并且该数组仅占用N * sizeof(元素)空间。

这意味着[T; N][T; M]是不同的类型(当N!= M时)并且您无法将一个引用转换为另一个。

惯用解决方案是改为使用切片

fn foo(array: &[u32; 10]) -> &[u32] {
    &array[0..5]
}

切片包含指向数据的指针和数据的长度,从而将该逻辑从编译时间移动到运行时。

夜间生锈

您可以执行运行时检查切片的长度是否正确,并在一步中将其转换为数组:

#![feature(try_from)]

use std::convert::TryInto;

fn foo(array: &[u32; 10]) -> &[u32; 5] {
    array[0..5].try_into().unwrap()
}

fn main() {}

不安全的锈病

因为有人可能想在早期版本的Rust中以不安全的方式执行此操作,所以我将提供代码based on the standard library implementation

fn foo(array: &[u32; 10]) -> &[u32; 5] {
    let slice = &array[0..5];

    if slice.len() == 5 {
        let ptr = slice.as_ptr() as *const [u32; 5];
        unsafe { &*ptr }
    } else {
        panic!("Needs to be length 5")
    }
}

fn main() {
    let input = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    let output = foo(&input);
    println!("{:?}", output);
}