use std::io::{Read, Seek, Write};
use crate::Result;
pub mod file;
pub mod memory;
pub mod sliced;
pub use file::FileBackend;
pub use memory::MemoryBackend;
pub use sliced::SlicedBackend;
pub trait BlockDevice: Read + Write + Seek + Send {
fn block_size(&self) -> u32;
fn total_size(&self) -> u64;
fn zero_range(&mut self, offset: u64, len: u64) -> Result<()> {
let size = self.total_size();
if offset.checked_add(len).is_none_or(|end| end > size) {
return Err(crate::Error::OutOfBounds { offset, len, size });
}
if len == 0 {
return Ok(());
}
self.seek(std::io::SeekFrom::Start(offset))?;
let zero = [0u8; 4096];
let mut remaining = len;
while remaining > 0 {
let n = remaining.min(zero.len() as u64) as usize;
self.write_all(&zero[..n])?;
remaining -= n as u64;
}
Ok(())
}
fn sync(&mut self) -> Result<()>;
fn read_at(&mut self, offset: u64, buf: &mut [u8]) -> Result<()> {
let size = self.total_size();
let end = offset
.checked_add(buf.len() as u64)
.ok_or(crate::Error::OutOfBounds {
offset,
len: buf.len() as u64,
size,
})?;
if end > size {
return Err(crate::Error::OutOfBounds {
offset,
len: buf.len() as u64,
size,
});
}
self.seek(std::io::SeekFrom::Start(offset))?;
self.read_exact(buf)?;
Ok(())
}
fn write_at(&mut self, offset: u64, buf: &[u8]) -> Result<()> {
let size = self.total_size();
let end = offset
.checked_add(buf.len() as u64)
.ok_or(crate::Error::OutOfBounds {
offset,
len: buf.len() as u64,
size,
})?;
if end > size {
return Err(crate::Error::OutOfBounds {
offset,
len: buf.len() as u64,
size,
});
}
self.seek(std::io::SeekFrom::Start(offset))?;
self.write_all(buf)?;
Ok(())
}
}