Почему шаблон с .. в массиве сохраняет фиксированное число элементов, а в срезе может соответствовать произвольному количеству?
Массив имеет длину, известную на этапе компиляции, поэтому .. в его шаблоне обозначает пропущенные элементы с фиксированным количеством. Срез хранит длину во время выполнения, поэтому .. может соответствовать любому количеству элементов, включая ноль, если остальные части шаблона допускают такую длину.
Шаблоны Rust предназначены для структурного разбора значений с сохранением проверяемой исчерпывающей сопоставимости. Для массивов важно сохранить гарантию фиксированной длины, а для срезов — выразить разбор последовательностей переменной длины без ручной проверки индексов.
Такой подход объединяет синтаксис сопоставления фиксированных и динамических последовательностей, но сохраняет различие между типами: массив содержит длину в самом типе, а срез представляет представление над последовательностью и хранит длину отдельно от типа элемента.
Неверно считать, что .. всегда означает «любое количество элементов». В шаблоне массива количество пропущенных позиций вычисляется из длины массива и явно указанных элементов; если длина не подходит, шаблон невозможно применить.
Для среза количество элементов в области .. определяется фактической длиной среза. Поэтому шаблон может успешно сопоставиться с срезами разной длины, но конкретные обязательные элементы до и после .. всё равно должны существовать.
Рассмотрим минимальный пример:
В первом шаблоне .. поглощает все элементы между первым и последним. Для среза из двух элементов эта область пуста, для более длинного среза она содержит промежуточные элементы. Срез из нуля или одного элемента не подходит, потому что шаблон требует отдельные первый и последний элементы.
В массиве логика другая: его длина известна. Например, шаблон с первым и последним элементами для массива из пяти элементов означает, что .. соответствует ровно трём позициям, а не произвольному числу. Для массива другой длины это уже другой шаблон по смыслу и он не подходит автоматически.
Само .. не создаёт переменную и не сохраняет пропущенные элементы. Если остаток требуется использовать, его можно связать именем через конструкцию остаточного связывания, после чего для среза это связывание представляет соответствующий подсрез. Остаток по-прежнему должен быть единственным в одном уровне шаблона.
Важно отличать шаблон от диапазона: .. не проверяет значения элементов и не означает диапазон чисел. Он управляет структурой последовательности, а дополнительные условия или вложенные шаблоны проверяют содержимое.
В обработчике сетевого пакета нужно проверить заголовок и последний байт полезной нагрузки. Вариант с индексацией требует отдельно проверять длину перед каждым обращением, иначе возможна паника при коротком пакете.
Можно сопоставлять только массив фиксированного размера. Это даёт строгую проверку длины, но не подходит для пакетов переменного размера. Можно использовать срез и несколько проверок длины вручную, однако такой код более многословен и легко расходится с последующей логикой обработки.
Выбран шаблон среза и ..: обязательные части выражают минимальную длину, а остаток покрывает произвольную полезную нагрузку. В результате короткие пакеты попадают в безопасную fallback-ветвь, а корректные разбираются без выхода за границы.
.. в шаблоне среза соответствовать нулю элементов?Да. Если остальные части шаблона согласуются с длиной среза, остаток может быть пустым. Например, шаблон, требующий первый и последний элементы, допускает срез длины два: между ними нет элементов.
.. в одном шаблоне среза, чтобы отдельно связать середину?Нет. Остаточная область должна быть однозначной, поэтому на одном уровне шаблона допускается только один ... Два независимых остатка не позволили бы Rust определить, сколько элементов относится к каждому из них.
.. в шаблоне массива означает, что длина массива неизвестна?Нет. Тип массива уже содержит длину, поэтому компилятор знает точное количество пропущенных позиций. В шаблоне массива .. сокращает запись перечисления оставшихся позиций, но не ослабляет проверку длины и не превращает массив в срез.