tape: introduce trait BlockRead

This commit is contained in:
Dietmar Maurer
2021-03-29 10:09:49 +02:00
parent c47609fedb
commit 0db5712493
6 changed files with 146 additions and 82 deletions

View File

@ -1,56 +1,46 @@
use std::io::{self, Read};
use std::io::Read;
use crate::tape::file_formats::PROXMOX_TAPE_BLOCK_SIZE;
use proxmox::tools::io::ReadExt;
use crate::tape::{
BlockRead,
BlockReadStatus,
file_formats::PROXMOX_TAPE_BLOCK_SIZE,
};
/// Emulate tape read behavior on a normal Reader
///
/// Tapes reads are always return one whole block PROXMOX_TAPE_BLOCK_SIZE.
pub struct EmulateTapeReader<R> {
pub struct EmulateTapeReader<R: Read> {
reader: R,
got_eof: bool,
}
impl <R: Read> EmulateTapeReader<R> {
pub fn new(reader: R) -> Self {
Self { reader }
Self { reader, got_eof: false }
}
}
impl <R: Read> Read for EmulateTapeReader<R> {
fn read(&mut self, mut buffer: &mut [u8]) -> Result<usize, io::Error> {
let initial_buffer_len = buffer.len(); // store, check later
let mut bytes = 0;
while !buffer.is_empty() {
match self.reader.read(buffer) {
Ok(0) => break,
Ok(n) => {
bytes += n;
let tmp = buffer;
buffer = &mut tmp[n..];
impl <R: Read> BlockRead for EmulateTapeReader<R> {
fn read_block(&mut self, buffer: &mut [u8]) -> Result<BlockReadStatus, std::io::Error> {
if self.got_eof {
proxmox::io_bail!("detected read after EOF!");
}
match self.reader.read_exact_or_eof(buffer)? {
false => {
self.got_eof = true;
Ok(BlockReadStatus::EndOfFile)
}
true => {
// test buffer len after EOF test (to allow EOF test with small buffers in BufferedReader)
if buffer.len() != PROXMOX_TAPE_BLOCK_SIZE {
proxmox::io_bail!("EmulateTapeReader: read_block with wrong block size ({} != {})",
buffer.len(), PROXMOX_TAPE_BLOCK_SIZE);
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
Ok(BlockReadStatus::Ok(buffer.len()))
}
}
if bytes == 0 {
return Ok(0);
}
// test buffer len after EOF test (to allow EOF test with small buffers in BufferedReader)
if initial_buffer_len != PROXMOX_TAPE_BLOCK_SIZE {
proxmox::io_bail!("EmulateTapeReader: got read with wrong block size ({} != {})",
buffer.len(), PROXMOX_TAPE_BLOCK_SIZE);
}
if !buffer.is_empty() {
Err(io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
} else {
Ok(bytes)
}
}
}