tape: introduce trait BlockRead
This commit is contained in:
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user