我正在编写需要64字节块的代码,并且我想在类型级别上强制使用此大小:
fn f(buf: &[u8; 64]) { ... }
但是,数据作为切片&[u8]
进入。因此,我希望能够使用此子空间并将其转换为&[u8; 64]
。事实证明,以下转换有效:
let buf = (0..64).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之间(包括0和32),该转换有效,但对于32以上的尺寸无效。我可以做些什么来启用此&[u8]
-> &[u8; 64]
转换而无需手动执行数据复制?
如果需要,可以将the code that Rust currently uses用于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
可能会被删除。在此之前,您可以实现自己的功能。晚上使用启用了常量泛型的函数,或者只是针对您的特定大小使用一个函数。
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(()))
}
}