Мне нужно прочитать запись данных фиксированного размера. Если данные недоступны, это законное условие EOF (не ошибка). Если есть какие-то данные, но их недостаточно для заполнения буфера записи, функция должна вернуть ошибку UnexpectedEof
. Функция будет неоднократно вызываться во входном потоке до тех пор, пока не встретится EOF.
Пример подписи (возвращаемое значение представляет EOF):
fn read_into(r: &mut impl Read, mut buff: &mut [u8])
-> io::Result<bool>
Я ожидал, что это приведет к более или менее единичному вызов r.read_exact(buf)
, но это не работает, потому что результат ошибки UnexpectedEof
не предоставляет информацию о том, сколько байтов было прочитано успешно. Я закончил со следующей реализацией ( детская площадка ):
use std::io::{self, Read};
fn read_into(r: &mut impl Read, mut buff: &mut [u8]) -> io::Result<bool> {
let mut partial = false;
while !buff.is_empty() {
match r.read(buff)? {
0 if partial => {
return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "Incomplete"));
}
0 => return Ok(true),
len => {
buff = &mut buff[len..];
partial = true;
}
}
}
Ok(false)
}
Кажется, что много кода для обработки чтения записей фиксированного размера, поэтому мой вопрос: можно ли это сделать более элегантно?
Было бы вполне нормально потребовать BufRead
, связанный с r
, или даже иметь функцию, принимающую конкретную BufReader<R>
struct.