let some_datagram [u8; 8] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
let a : &[u8; 2] = some_datagram[0..2];
let b : &[u8; 4] = some_datagram[2..6];
let c : &[u8; 2] = some_datagram[6..8];

Вышеупомянутое не будет работать, потому что some_datagram[0..2] - это &[u8], а не &[u8; 2]. Это имеет смысл при использовании других типов Range*, где начальная/конечная точки неизвестны во время компиляции. Я знаю, что существует реализация TryInto для &[u8] в &[u8; n], но, поскольку все это известно во время компиляции, меня беспокоит необходимость иметь дело с случаем ошибки, который, как я знаю, не может случаться.

Есть ли альтернативный метод, кроме [], который возвращает массив фиксированного размера? Может стандартный макрос?

1
Huckle 5 Апр 2020 в 01:47
"Меня беспокоит необходимость иметь дело с ошибкой, которая, как я знаю, не может произойти". Вот для чего нужны .unwrap и .expect. Застенчивый из-за того, что у компилятора есть непоследовательные правила, когда разрешены преобразования, на самом деле нет другого способа выразить это.
 – 
Brian
5 Апр 2020 в 02:00
«на самом деле нет другого способа выразить это», ну, есть, но это очень уродливо. &[some_datagram[0], some_datagram[1]] равно &[u8; 2], но было бы неплохо, если бы язык дал вам немного синтаксического сахара.
 – 
Huckle
5 Апр 2020 в 02:03

1 ответ

Контейнер array_macro экспортирует макрос array!, который позволяет создавать массивы с использованием обратного вызова по индексам нового массива. Документация иллюстрирует это следующим примером:

assert_eq!(array![|x| x; 3], [0, 1, 2]);

В вашем случае вы можете выполнить преобразование среза в массив с помощью операторов

let a : &[u8; 2] = array![|i| some_datagram[i    ]; 2];
let b : &[u8; 4] = array![|i| some_datagram[i + 2]; 4];
let c : &[u8; 2] = array![|i| some_datagram[i + 6]; 2];

Является ли это более или менее читаемым, чем использование стандартной реализации TryInto и .unwrap, зависит от мнения. Поскольку это сторонний крейт, вы также должны учитывать тот факт, что большинство разработчиков, читающих этот код, не обязательно будут знакомы с тем, что делает макрос array!.

1
Brian 5 Апр 2020 в 02:17
Проголосовал, потому что это технически работающий ответ, но по причинам, которые вы упомянули, я пропущу. К сожалению, на практике мне нужно [u8; 44], что выходит за рамки того, что будет поддерживать TryInto (пока).
 – 
Huckle
5 Апр 2020 в 02:24
В итоге нашел ящик arrayref, в котором есть макрос array_ref!(array, start, end). Пока у rustc не появится возможность делать это изначально, так и будет.
 – 
Huckle
5 Апр 2020 в 02:32