Как конвертировать & [u8] в & [u8;64]? - PullRequest
0 голосов
/ 21 октября 2019

Я пишу код, который занимает 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 Ответ

1 голос
/ 21 октября 2019

При желании вы можете использовать код, который в настоящее время использует 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 предположительно будетудалить. До этого вы можете реализовать свою собственную функцию. Либо используйте каждую ночь с включенными постоянными генериками, либо просто используйте функцию для вашего определенного размера.

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(()))
    }
}

(детская площадка)

...