如何将 &[u8] 转换为 &[u8; 64]?

3

我正在编写代码,处理64字节块,并且我想在类型级别上强制执行此大小:

fn f(buf: &[u8; 64]) { ... }

然而,数据以切片&[u8]的形式传入。因此,我想能够将其分成子空间并转换为&[u8; 64]。结果证明以下转换有效:

let buf = (0..32).collect::<Vec<u8>>();
let z: &[u8; 32] = &(&buf[..]).try_into().unwrap();

但以下内容不行:
let buf = (0..64).collect::<Vec<u8>>();
let z: &[u8; 64] = &(&buf[..]).try_into().unwrap();

当转换的大小在0到32之间时,可以进行转换,但对于大于32的大小则不行。我该如何在不手动复制数据的情况下启用 &[u8] -> &[u8; 64] 的转换?

1个回答

2
如果需要的话,您可以使用 Rust 目前使用的代码来处理 0-32 大小的值。
#[stable(feature = "try_from", since = "1.34.0")]
impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N]
where
    [T; N]: LengthAtMost32,
{
    type Error = TryFromSliceError;

    fn try_from(slice: &[T]) -> Result<&[T; N], TryFromSliceError> {
        if slice.len() == N {
            let ptr = slice.as_ptr() as *const [T; N];
            unsafe { Ok(&*ptr) }
        } else {
            Err(TryFromSliceError(()))
        }
    }
}

当常量泛型被稳定下来时,绑定 [T; N]: LengthAtMost32 可能会被移除。在那之前,您可以实现自己的函数。要么使用启用了常量泛型的 nightly 版本,要么为您特定的大小编写一个函数。
struct TryFromSliceError(());

fn slice_to_array_64<T>(slice: &[T]) -> Result<&[T; 64], TryFromSliceError> {
    if slice.len() == 64 {
        let ptr = slice.as_ptr() as *const [T; 64];
        unsafe {Ok(&*ptr)}
    } else {
        Err(TryFromSliceError(()))
    }
}

中文翻译:

(游乐场)


你还可以写struct TryFromSliceError;并使用Err(TryFromSliceError)创建一个实例,这样你就不需要将单元类型作为结构体成员。 - undefined
@你好 是的。我只是复制了标准库中的内容。我认为这样做是为了防止在模块之外创建实例。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接