Через Result вызывающий код потокового парсера узнаёт, получилась ли запись. Но сдвинул ли парсер курсор, тронул ли рабочую память, оставил ли вход нетронутым, из него не видно, а после неполной записи важно именно это. Кому теперь принадлежат эти байты и откуда начнётся следующий вызов?
Предлагаю такую схему. Байтовый вектор принадлежит вызывающему коду, парсеру он одалживает разделяемый срез. Курсор и временно декодированные поля принадлежат парсеру. При успехе курсор переходит за одну полную запись. При неполном входе он остаётся в начале этой записи, а предварительные поля отбрасываются. При некорректном входе начало тоже сохраняется, а возвращается смещение ошибки. Диагностика неполного входа содержит начало записи и позицию, до которой дошло сканирование. Эта позиция говорит о том, что просмотрено, и ничего не потребляет.
Сам по себе возврат Err ничего из этого не даёт. Парсер должен накапливать изменения и фиксировать их только при успехе. Тогда вызывающий код хранит непотреблённый остаток, дописывает байты и повторяет попытку. Но если успешная запись заимствует данные из вектора, какое чтение ещё использует ссылку в момент дописывания? Его нужно закончить раньше.
Если забрать вектор во владение, появится свой вопрос, возвращать ли его при сбое. Заимствование этого вопроса не создаёт, но позицию сбоя и допустимые следующие вызовы всё равно стоит описать в документации.