меня это http, но в примере я сэмулировал вектором). Буфер выдаёт их пачками по 8192 байта. Я могу потреблять только кратное 20 количество байт, потому что я собираю это в структуру размером 20 байт и отправляю дальше. Я точно знаю, что когда прочитаю весь буфер, то количество данных будет кратно 20 байт.
Но в моей имплементации всё ломается, потому что io::copy довольно тупой - он пытается опустошить весь временный буфер на 8192 байта, вместо того, чтобы присоединить остаток 12 байт к следующей пачке, и отправить мне больший размер.
Я в теории могу сам закостылить и хранить хвост между вызовами write, но нет ли готовых нормальных решений? Попытка обернуть в BufWriter не помогает, ломается в том же месте.
Так откуда оно может знать будет следующая пачка или нет
Оно сразу роняет ошибку при получении Ok(0). https://doc.rust-lang.org/src/std/io/copy.rs.html#278 https://doc.rust-lang.org/src/std/io/mod.rs.html#1624 Вместо этого можно было бы попытаться перенести остаток буфера, попытаться получить от ридера ещё данных и попытаться записать. И вот если тогда Ok(0), то уже всё плохо, да. По итогу я пока так и закостылил поверх. Но выходит лишняя реаллокация буфера (чего можно было бы избежать если бы имплементация внутри io была другая). Так-то мне некритично, всё равно расходы на IO сильно больше, но грустно
ещё раз что нужно и почему хранить хвост это костыль?
Нужно чтобы код по ссылке не падал с ошибкой) Падает потому что write может читать только количество байт кратное 20. Хранить хвост самому кажется костылём, потому что абстракция не строится. Мне такое надо несколько раз, поэтому не хочу копипастить управление хвостом во все места. А если делать снаружи, то выходит, что я имею хвост и буффер и мне надо реаллоцировать буффер (делая из него хвост + буфер), чтобы прокинуть его дальше.
Кажется что Write этот просто должен есть данные, а настоящие записи уносить в другой поток (ну или прям на месте писать куда это нужно записать) где будут записывать по 20 байт. И тогда по идее аллокация нужна будет только на эти 20 байт которые не влезли.
на самом деле мне кажется, что задача должна как-то уже решаться в сообществе. Людям же приходится десериализовать бинарные данные в структуры из потока байт. Ну там какой-нибудь протобаф через grpc условно. Только уровень вложенности абстракций с макросами в опенсорсе мне пока не позволил добраться до понимания. Ещё видимо вернусь к этому после выходных
а зачем там реаллок?
Чтобы из хвост+буфер сделать один буфер
сделай struct Writer { len: usize, buf: [u8; SIZE] }
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=b55a06eb9025cf18fa493597457185d7 Накидал чего-то такого, может бажинить, но выглядит работающим :) (размер чанка на 800 поменял, чтобы консоль не засрало)
Спасибо, только я завтра уже почитаю.
Я про само io, оно не знает как устроен твой application layer protocol
Обсуждают сегодня