Skip to content

Commit 2a60468

Browse files
committed
Add a general BlockCache.
Avoids needing to stack allocate 512 byte blocks.
1 parent 92b0c6a commit 2a60468

File tree

5 files changed

+358
-352
lines changed

5 files changed

+358
-352
lines changed

src/blockdevice.rs

+72
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,78 @@ pub trait BlockDevice {
8686
fn num_blocks(&self) -> Result<BlockCount, Self::Error>;
8787
}
8888

89+
/// A caching layer for block devices
90+
///
91+
/// Caches a single block.
92+
#[derive(Debug)]
93+
pub struct BlockCache<D> {
94+
block_device: D,
95+
block: [Block; 1],
96+
block_idx: Option<BlockIdx>,
97+
}
98+
99+
impl<D> BlockCache<D>
100+
where
101+
D: BlockDevice,
102+
{
103+
/// Create a new block cache
104+
pub fn new(block_device: D) -> BlockCache<D> {
105+
BlockCache {
106+
block_device,
107+
block: [Block::new()],
108+
block_idx: None,
109+
}
110+
}
111+
112+
/// Read a block, and return a reference to it.
113+
pub fn read(&mut self, block_idx: BlockIdx) -> Result<&Block, D::Error> {
114+
if self.block_idx != Some(block_idx) {
115+
self.block_device.read(&mut self.block, block_idx)?;
116+
self.block_idx = Some(block_idx);
117+
}
118+
Ok(&self.block[0])
119+
}
120+
121+
/// Read a block, and return a reference to it.
122+
pub fn read_mut(&mut self, block_idx: BlockIdx) -> Result<&mut Block, D::Error> {
123+
if self.block_idx != Some(block_idx) {
124+
self.block_device.read(&mut self.block, block_idx)?;
125+
self.block_idx = Some(block_idx);
126+
}
127+
Ok(&mut self.block[0])
128+
}
129+
130+
/// Write back a block you read with [`Self::read_mut`] and then modified.
131+
pub fn write_back(&mut self) -> Result<(), D::Error> {
132+
self.block_device.write(
133+
&self.block,
134+
self.block_idx.expect("write_back with no read"),
135+
)
136+
}
137+
138+
/// Access a blank sector
139+
pub fn blank_mut(&mut self, block_idx: BlockIdx) -> &mut Block {
140+
self.block_idx = Some(block_idx);
141+
for b in self.block[0].iter_mut() {
142+
*b = 0;
143+
}
144+
&mut self.block[0]
145+
}
146+
147+
/// Access the block device
148+
pub fn block_device(&mut self) -> &mut D {
149+
// invalidate the cache
150+
self.block_idx = None;
151+
// give them the block device
152+
&mut self.block_device
153+
}
154+
155+
/// Get the block device back
156+
pub fn free(self) -> D {
157+
self.block_device
158+
}
159+
}
160+
89161
/// The linear numeric address of a block (or sector).
90162
///
91163
/// The first block on a disk gets `BlockIdx(0)` (which usually contains the

src/fat/mod.rs

-31
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,6 @@ pub enum FatType {
1414
Fat32,
1515
}
1616

17-
pub(crate) struct BlockCache {
18-
block: Block,
19-
idx: Option<BlockIdx>,
20-
}
21-
impl BlockCache {
22-
pub fn empty() -> Self {
23-
BlockCache {
24-
block: Block::new(),
25-
idx: None,
26-
}
27-
}
28-
pub(crate) fn read<D>(
29-
&mut self,
30-
block_device: &D,
31-
block_idx: BlockIdx,
32-
) -> Result<&Block, Error<D::Error>>
33-
where
34-
D: BlockDevice,
35-
{
36-
if Some(block_idx) != self.idx {
37-
self.idx = Some(block_idx);
38-
block_device
39-
.read(core::slice::from_mut(&mut self.block), block_idx)
40-
.map_err(Error::DeviceError)?;
41-
}
42-
Ok(&self.block)
43-
}
44-
}
45-
4617
mod bpb;
4718
mod info;
4819
mod ondiskdirentry;
@@ -53,8 +24,6 @@ pub use info::{Fat16Info, Fat32Info, FatSpecificInfo, InfoSector};
5324
pub use ondiskdirentry::OnDiskDirEntry;
5425
pub use volume::{parse_volume, FatVolume, VolumeName};
5526

56-
use crate::{Block, BlockDevice, BlockIdx, Error};
57-
5827
// ****************************************************************************
5928
//
6029
// Unit Tests

0 commit comments

Comments
 (0)