Я перевожу часть (2000 строк) проприетарного кода на C в Rust.В C обычно указатель, индекс массива и т. Д. Обычно запускаются, пока они не отрицательны.В Rust, упрощенном до костей, это будет выглядеть примерно так:
while i >= 0 && more_conditions {
more_work;
i -= 1;
}
Конечно, когда i
равно usize
, вы получаете переполнение от вычитания.Я научился обходить эту проблему, используя for
циклы с .rev()
, смещая мои индексы на единицу, или используя другой тип и приводя с as usize
и т. Д.
Обычно это работает, и обычноЯ могу сделать его разборчивым, но код, который я изменяю, переполнен индексами, идущими навстречу друг другу, и в конечном итоге протестирован с i_low > i_high
Что-то вроде (в Rust)
loop {
while condition1(i_low) { i_low += 1; }
while condition2(i_high) { j_high -= 1; }
if i_low > i_high { return something; }
do_something_else;
}
Время от времени эта паника возникает, когда i_high
проходит мимо 0.
Я вставил в код много j_high >= 0 &&
, и он стал намного менее читабельным.
Как опытные программисты на Rust избегают usize
переменных, идущих в -1?
для циклов?for i in (0..size).rev()
литье?i as usize
, после проверки i < 0
смещения вашей переменной на единицу и использования i-1
в безопасном режиме?
дополнительные условия?
ловить исключения?
Или вы в конечном итоге научились писать программы в таких ситуациях?
Пояснение: код C не нарушен - он предположительно находится в производстве в течение десяти лет, структурируя видео сегменты на нескольких серверах 24/7.Он просто не следует соглашениям Rust - он часто возвращает -1 в качестве индекса, он возвращается с -1 для низкого индекса обрабатываемого массива, и индексы все время становятся отрицательными.Все они обрабатываются до возникновения проблем - безобразно, но функционально.Примерно так:
incident_segment = detect_incident(array, start, end);
attach(array, incident_segment);
store(array, start, incident_segment - 1);
process(array, incident_segment + 1, end);
В приведенном выше коде каждый из трех результирующих вызовов может получить индекс сегмента, равный -1 (присоединить, сохранить) или выйти за пределы (процесс). Он обрабатывается, но послевызов.
Кажется, работает и мой код Rust.На самом деле, чтобы справиться с отрицательным использованием, я добавил дополнительную логику, которая сокращает количество рекурсий, поэтому он работает примерно так же быстро, как и код C (очевидно, быстрее, но это также потому, что я распределил вывод по несколькимдиски)
Проблема в том, что клиент не хочет полной перезаписи и хочет, чтобы «нативные» программисты могли проверять две программы друг против друга.Исходя из полученных ответов, я думаю, что использование i64 и приведение / теневое копирование по мере необходимости могут быть лучшим способом создания кода, который легко читать для «нативов».Что мне лично не должно нравиться ...