从切片构建数组的正确方法?

时间:2015-04-11 03:04:04

标签: arrays rust slice

好吧,这看起来有点傻,但是我找不到函数从片的内容返回一个静态大小的数组。

阵列和切片上的Rust Book部分对此一无所知。 (它确实显示了如何从数组中获取切片,但我想采用相反的方式。)我还检查了std::slicestd::array的文档,但是如果它在那里,我不是看到它。

当然可以选择逐个写出每个元素,但这看起来很荒谬。现在,我最终为我做了一个python单行程。

", ".join(["k[{}]".format(i) for i in range(32)])

所以我最终得到了这个:

use db_key::Key;

#[derive(Clone)]
pub struct Sha256{
    bits : [u8;32]
}

impl Key for Sha256 {
    fn from_u8(k: &[u8]) -> Self {
        Sha256{bits:
               // FIXME: This is dumb.
               [ k[0], k[1], k[2], k[3], k[4], k[5], k[6], k[7], k[8], k[9], k[10], k[11], k[12], k[13], k[14], k[15], k[16], k[17], k[18], k[19], k[20], k[21], k[22], k[23], k[24], k[25], k[26], k[27], k[28], k[29], k[30], k[31] ]
        }
    }
    fn as_slice<T, F: Fn(&[u8]) -> T>(&self, f: F) -> T {
        f(&self.bits)
    }
}

我想知道是否有正确的方法,例如k.to_array(32)或类似的东西。

而且,是的,我意识到上述代码可能会因越界访问而失败。我不确定db_key::Key对无效输入的期望。

编辑:

Is there a good way to convert a Vec to an array?类似但不太通用。对于这个问题,一个很好的答案可能也是一个很好的答案,只需要从vec中获取一个切片,这可以有效而简洁地完成。我也不认为“为你关心的每个尺寸编写单独的转换函数”是一个合适的解决方案。

How to get a slice as a static array in rust?也类似,但接受的答案是我已经独立提出的黑客攻击。

1 个答案:

答案 0 :(得分:2)

你可以使用一个循环来解决它简单(但可能令人失望)的方式:

let input = b"abcdef";
let mut array = [0u8; 32];
for (x, y) in input.iter().zip(array.iter_mut()) {
    *y = *x;
}

我们可以使用函数来执行运行时大小检查,并将切片转换为对固定大小数组的引用。

Libstd没有提供足够的特性来可靠地检查输入和输出类型是否匹配,但理论上我们可以自己开发(对于有限数量的数组类型)。无论哪种方式,演员表都是这样, U 是您指定的任意数组类型。

/// Return a reference to a fixed size array from a slice.
///
/// Return **Some(array)** if the dimensions match, **None** otherwise.
///
/// **Note:** Unsafe because we can't check if the **U** type is really an array.
pub unsafe fn as_array<T, U>(xs: &[T]) -> Option<&U> where
    U: AsRef<[T]>,
{
    let sz = std::mem::size_of::<U>();
    let input_sz = xs.len() * std::mem::size_of::<T>();

    // The size check could be relaxed to sz <= input_sz
    if sz == input_sz {
        Some(&*(xs.as_ptr() as *const U))
    } else {
        None
    }
}