use crate::{BlockIo, DiskError, SliceBlockIoError};
use gpt_disk_types::{BlockSize, Lba};
use std::error::Error;
use std::fmt::{Debug, Display};
use std::io::{self, Read, Seek, SeekFrom, Write};
pub struct StdBlockIo<'a, T>
where
T: Read + Write + Seek,
{
file: &'a mut T,
block_size: BlockSize,
}
impl<'a, T> StdBlockIo<'a, T>
where
T: Read + Write + Seek,
{
pub fn new(file: &'a mut T, block_size: BlockSize) -> Self {
Self { file, block_size }
}
}
impl<'a, T> BlockIo for StdBlockIo<'a, T>
where
T: Read + Write + Seek,
{
type Error = io::Error;
fn block_size(&self) -> BlockSize {
self.block_size
}
fn num_blocks(&mut self) -> Result<u64, Self::Error> {
let block_size = self.block_size().to_u64();
let num_bytes = self.file.seek(SeekFrom::End(0))?;
Ok(num_bytes / block_size)
}
fn read_blocks(
&mut self,
start_lba: Lba,
dst: &mut [u8],
) -> Result<(), Self::Error> {
self.assert_valid_buffer(dst);
self.file.seek(SeekFrom::Start(
start_lba.to_u64() * self.block_size().to_u64(),
))?;
self.file.read_exact(dst)?;
Ok(())
}
fn write_blocks(
&mut self,
start_lba: Lba,
src: &[u8],
) -> Result<(), Self::Error> {
self.assert_valid_buffer(src);
self.file.seek(SeekFrom::Start(
start_lba.to_u64() * self.block_size().to_u64(),
))?;
self.file.write_all(src)?;
Ok(())
}
fn flush(&mut self) -> Result<(), Self::Error> {
self.file.flush()
}
}
impl<Custom> Error for DiskError<Custom> where Custom: Debug + Display {}
impl Error for SliceBlockIoError {}