ax-driver-block 0.3.14

Common traits and types for block storage drivers
Documentation
use super::PartitionRegion;
use crate::{BaseDriverOps, BlockDriverOps, DevError, DevResult, DeviceType};

pub struct PartitionBlockDevice<T> {
    inner: T,
    region: PartitionRegion,
}

impl<T: BlockDriverOps> PartitionBlockDevice<T> {
    pub const fn new(inner: T, region: PartitionRegion) -> Self {
        Self { inner, region }
    }

    pub const fn region(&self) -> PartitionRegion {
        self.region
    }

    fn check_io_bounds(&self, block_id: u64, buf_len: usize) -> DevResult {
        let block_size = self.inner.block_size();
        if block_size == 0 || !buf_len.is_multiple_of(block_size) {
            return Err(DevError::InvalidParam);
        }

        let blocks = u64::try_from(buf_len / block_size).map_err(|_| DevError::BadState)?;
        let end_block = block_id.checked_add(blocks).ok_or(DevError::BadState)?;
        if end_block > self.num_blocks() {
            return Err(DevError::InvalidParam);
        }

        Ok(())
    }
}

impl<T: BlockDriverOps> BaseDriverOps for PartitionBlockDevice<T> {
    fn device_name(&self) -> &str {
        self.inner.device_name()
    }

    fn device_type(&self) -> DeviceType {
        self.inner.device_type()
    }

    fn irq_num(&self) -> Option<usize> {
        self.inner.irq_num()
    }
}

impl<T: BlockDriverOps> BlockDriverOps for PartitionBlockDevice<T> {
    fn num_blocks(&self) -> u64 {
        self.region.num_blocks()
    }

    fn block_size(&self) -> usize {
        self.inner.block_size()
    }

    fn read_block(&mut self, block_id: u64, buf: &mut [u8]) -> DevResult {
        self.check_io_bounds(block_id, buf.len())?;
        self.inner.read_block(self.region.start_lba + block_id, buf)
    }

    fn write_block(&mut self, block_id: u64, buf: &[u8]) -> DevResult {
        self.check_io_bounds(block_id, buf.len())?;
        self.inner
            .write_block(self.region.start_lba + block_id, buf)
    }

    fn flush(&mut self) -> DevResult {
        self.inner.flush()
    }
}