use axdriver::prelude::*;
const BLOCK_SIZE: usize = 512;
pub struct Disk {
block_id: u64,
offset: usize,
dev: AxBlockDevice,
}
impl Disk {
pub fn new(dev: AxBlockDevice) -> Self {
assert_eq!(BLOCK_SIZE, dev.block_size());
Self {
block_id: 0,
offset: 0,
dev,
}
}
pub fn size(&self) -> u64 {
self.dev.num_blocks() * BLOCK_SIZE as u64
}
pub fn position(&self) -> u64 {
self.block_id * BLOCK_SIZE as u64 + self.offset as u64
}
pub fn set_position(&mut self, pos: u64) {
self.block_id = pos / BLOCK_SIZE as u64;
self.offset = pos as usize % BLOCK_SIZE;
}
pub fn read_one(&mut self, buf: &mut [u8]) -> DevResult<usize> {
let read_size = if self.offset == 0 && buf.len() >= BLOCK_SIZE {
self.dev
.read_block(self.block_id, &mut buf[0..BLOCK_SIZE])?;
self.block_id += 1;
BLOCK_SIZE
} else {
let mut data = [0u8; BLOCK_SIZE];
let start = self.offset;
let count = buf.len().min(BLOCK_SIZE - self.offset);
if start > BLOCK_SIZE {
info!("block size: {} start {}", BLOCK_SIZE, start);
}
self.dev.read_block(self.block_id, &mut data)?;
buf[..count].copy_from_slice(&data[start..start + count]);
self.offset += count;
if self.offset >= BLOCK_SIZE {
self.block_id += 1;
self.offset -= BLOCK_SIZE;
}
count
};
Ok(read_size)
}
pub fn write_one(&mut self, buf: &[u8]) -> DevResult<usize> {
let write_size = if self.offset == 0 && buf.len() >= BLOCK_SIZE {
self.dev.write_block(self.block_id, &buf[0..BLOCK_SIZE])?;
self.block_id += 1;
BLOCK_SIZE
} else {
let mut data = [0u8; BLOCK_SIZE];
let start = self.offset;
let count = buf.len().min(BLOCK_SIZE - self.offset);
self.dev.read_block(self.block_id, &mut data)?;
data[start..start + count].copy_from_slice(&buf[..count]);
self.dev.write_block(self.block_id, &data)?;
self.offset += count;
if self.offset >= BLOCK_SIZE {
self.block_id += 1;
self.offset -= BLOCK_SIZE;
}
count
};
Ok(write_size)
}
}