#[derive(Clone)]
pub struct Block {
pub contents: [u8; Block::LEN],
}
impl Block {
pub const LEN: usize = 512;
pub const LEN_U32: u32 = 512;
pub fn new() -> Block {
Block {
contents: [0u8; Self::LEN],
}
}
}
impl core::ops::Deref for Block {
type Target = [u8; 512];
fn deref(&self) -> &[u8; 512] {
&self.contents
}
}
impl core::ops::DerefMut for Block {
fn deref_mut(&mut self) -> &mut [u8; 512] {
&mut self.contents
}
}
impl core::fmt::Debug for Block {
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
writeln!(fmt, "Block:")?;
for line in self.contents.chunks(32) {
for b in line {
write!(fmt, "{:02x}", b)?;
}
write!(fmt, " ")?;
for &b in line {
if (0x20..=0x7F).contains(&b) {
write!(fmt, "{}", b as char)?;
} else {
write!(fmt, ".")?;
}
}
writeln!(fmt)?;
}
Ok(())
}
}
impl Default for Block {
fn default() -> Self {
Self::new()
}
}
pub trait BlockDevice {
type Error: core::fmt::Debug;
fn read(&self, blocks: &mut [Block], start_block_idx: BlockIdx) -> Result<(), Self::Error>;
fn write(&self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Self::Error>;
fn num_blocks(&self) -> Result<BlockCount, Self::Error>;
}
#[derive(Debug)]
pub struct BlockCache<D> {
block_device: D,
block: [Block; 1],
block_idx: Option<BlockIdx>,
}
impl<D> BlockCache<D>
where
D: BlockDevice,
{
pub fn new(block_device: D) -> BlockCache<D> {
BlockCache {
block_device,
block: [Block::new()],
block_idx: None,
}
}
pub fn read(&mut self, block_idx: BlockIdx) -> Result<&Block, D::Error> {
if self.block_idx != Some(block_idx) {
self.block_idx = None;
self.block_device.read(&mut self.block, block_idx)?;
self.block_idx = Some(block_idx);
}
Ok(&self.block[0])
}
pub fn read_mut(&mut self, block_idx: BlockIdx) -> Result<&mut Block, D::Error> {
if self.block_idx != Some(block_idx) {
self.block_idx = None;
self.block_device.read(&mut self.block, block_idx)?;
self.block_idx = Some(block_idx);
}
Ok(&mut self.block[0])
}
pub fn write_back(&mut self) -> Result<(), D::Error> {
self.block_device.write(
&self.block,
self.block_idx.expect("write_back with no read"),
)
}
pub fn write_back_with_duplicate(&mut self, duplicate: BlockIdx) -> Result<(), D::Error> {
self.block_device.write(
&self.block,
self.block_idx.expect("write_back with no read"),
)?;
self.block_device.write(&self.block, duplicate)?;
Ok(())
}
pub fn blank_mut(&mut self, block_idx: BlockIdx) -> &mut Block {
self.block_idx = Some(block_idx);
self.block[0].fill(0);
&mut self.block[0]
}
pub fn block_device(&mut self) -> &mut D {
self.block_idx = None;
&mut self.block_device
}
pub fn free(self) -> D {
self.block_device
}
}
#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct BlockIdx(pub u32);
impl BlockIdx {
pub fn into_bytes(self) -> u64 {
(u64::from(self.0)) * (Block::LEN as u64)
}
pub fn range(self, num: BlockCount) -> BlockIter {
BlockIter::new(self, self + BlockCount(num.0))
}
}
impl core::ops::Add<BlockCount> for BlockIdx {
type Output = BlockIdx;
fn add(self, rhs: BlockCount) -> BlockIdx {
BlockIdx(self.0 + rhs.0)
}
}
impl core::ops::AddAssign<BlockCount> for BlockIdx {
fn add_assign(&mut self, rhs: BlockCount) {
self.0 += rhs.0
}
}
impl core::ops::Sub<BlockCount> for BlockIdx {
type Output = BlockIdx;
fn sub(self, rhs: BlockCount) -> BlockIdx {
BlockIdx(self.0 - rhs.0)
}
}
impl core::ops::SubAssign<BlockCount> for BlockIdx {
fn sub_assign(&mut self, rhs: BlockCount) {
self.0 -= rhs.0
}
}
#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct BlockCount(pub u32);
impl core::ops::Add<BlockCount> for BlockCount {
type Output = BlockCount;
fn add(self, rhs: BlockCount) -> BlockCount {
BlockCount(self.0 + rhs.0)
}
}
impl core::ops::AddAssign<BlockCount> for BlockCount {
fn add_assign(&mut self, rhs: BlockCount) {
self.0 += rhs.0
}
}
impl core::ops::Sub<BlockCount> for BlockCount {
type Output = BlockCount;
fn sub(self, rhs: BlockCount) -> BlockCount {
BlockCount(self.0 - rhs.0)
}
}
impl core::ops::SubAssign<BlockCount> for BlockCount {
fn sub_assign(&mut self, rhs: BlockCount) {
self.0 -= rhs.0
}
}
impl BlockCount {
pub const fn from_bytes(byte_count: u32) -> BlockCount {
let mut count = byte_count / Block::LEN_U32;
if (count * Block::LEN_U32) != byte_count {
count += 1;
}
BlockCount(count)
}
pub fn offset_bytes(self, offset: u32) -> Self {
BlockCount(self.0 + (offset / Block::LEN_U32))
}
}
pub struct BlockIter {
inclusive_end: BlockIdx,
current: BlockIdx,
}
impl BlockIter {
pub const fn new(start: BlockIdx, inclusive_end: BlockIdx) -> BlockIter {
BlockIter {
inclusive_end,
current: start,
}
}
}
impl core::iter::Iterator for BlockIter {
type Item = BlockIdx;
fn next(&mut self) -> Option<Self::Item> {
if self.current.0 >= self.inclusive_end.0 {
None
} else {
let this = self.current;
self.current += BlockCount(1);
Some(this)
}
}
}