@@ -16,40 +16,6 @@ pub struct Block {
16
16
pub contents : [ u8 ; Block :: LEN ] ,
17
17
}
18
18
19
- /// The linear numeric address of a block (or sector).
20
- ///
21
- /// The first block on a disk gets `BlockIdx(0)` (which usually contains the
22
- /// Master Boot Record).
23
- #[ cfg_attr( feature = "defmt-log" , derive( defmt:: Format ) ) ]
24
- #[ derive( Debug , Copy , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
25
- pub struct BlockIdx ( pub u32 ) ;
26
-
27
- /// The a number of blocks (or sectors).
28
- ///
29
- /// Add this to a `BlockIdx` to get an actual address on disk.
30
- #[ cfg_attr( feature = "defmt-log" , derive( defmt:: Format ) ) ]
31
- #[ derive( Debug , Copy , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
32
- pub struct BlockCount ( pub u32 ) ;
33
-
34
- /// An iterator returned from `Block::range`.
35
- pub struct BlockIter {
36
- inclusive_end : BlockIdx ,
37
- current : BlockIdx ,
38
- }
39
-
40
- /// A block device - a device which can read and write blocks (or
41
- /// sectors). Only supports devices which are <= 2 TiB in size.
42
- pub trait BlockDevice {
43
- /// The errors that the `BlockDevice` can return. Must be debug formattable.
44
- type Error : core:: fmt:: Debug ;
45
- /// Read one or more blocks, starting at the given block index.
46
- fn read ( & self , blocks : & mut [ Block ] , start_block_idx : BlockIdx ) -> Result < ( ) , Self :: Error > ;
47
- /// Write one or more blocks, starting at the given block index.
48
- fn write ( & self , blocks : & [ Block ] , start_block_idx : BlockIdx ) -> Result < ( ) , Self :: Error > ;
49
- /// Determine how many blocks this device can hold.
50
- fn num_blocks ( & self ) -> Result < BlockCount , Self :: Error > ;
51
- }
52
-
53
19
impl Block {
54
20
/// All our blocks are a fixed length of 512 bytes. We do not support
55
21
/// 'Advanced Format' Hard Drives with 4 KiB blocks, nor weird old
@@ -67,64 +33,6 @@ impl Block {
67
33
}
68
34
}
69
35
70
- impl Default for Block {
71
- fn default ( ) -> Self {
72
- Self :: new ( )
73
- }
74
- }
75
-
76
- impl core:: ops:: Add < BlockCount > for BlockIdx {
77
- type Output = BlockIdx ;
78
- fn add ( self , rhs : BlockCount ) -> BlockIdx {
79
- BlockIdx ( self . 0 + rhs. 0 )
80
- }
81
- }
82
-
83
- impl core:: ops:: AddAssign < BlockCount > for BlockIdx {
84
- fn add_assign ( & mut self , rhs : BlockCount ) {
85
- self . 0 += rhs. 0
86
- }
87
- }
88
-
89
- impl core:: ops:: Add < BlockCount > for BlockCount {
90
- type Output = BlockCount ;
91
- fn add ( self , rhs : BlockCount ) -> BlockCount {
92
- BlockCount ( self . 0 + rhs. 0 )
93
- }
94
- }
95
-
96
- impl core:: ops:: AddAssign < BlockCount > for BlockCount {
97
- fn add_assign ( & mut self , rhs : BlockCount ) {
98
- self . 0 += rhs. 0
99
- }
100
- }
101
-
102
- impl core:: ops:: Sub < BlockCount > for BlockIdx {
103
- type Output = BlockIdx ;
104
- fn sub ( self , rhs : BlockCount ) -> BlockIdx {
105
- BlockIdx ( self . 0 - rhs. 0 )
106
- }
107
- }
108
-
109
- impl core:: ops:: SubAssign < BlockCount > for BlockIdx {
110
- fn sub_assign ( & mut self , rhs : BlockCount ) {
111
- self . 0 -= rhs. 0
112
- }
113
- }
114
-
115
- impl core:: ops:: Sub < BlockCount > for BlockCount {
116
- type Output = BlockCount ;
117
- fn sub ( self , rhs : BlockCount ) -> BlockCount {
118
- BlockCount ( self . 0 - rhs. 0 )
119
- }
120
- }
121
-
122
- impl core:: ops:: SubAssign < BlockCount > for BlockCount {
123
- fn sub_assign ( & mut self , rhs : BlockCount ) {
124
- self . 0 -= rhs. 0
125
- }
126
- }
127
-
128
36
impl core:: ops:: Deref for Block {
129
37
type Target = [ u8 ; 512 ] ;
130
38
fn deref ( & self ) -> & [ u8 ; 512 ] {
@@ -159,6 +67,107 @@ impl core::fmt::Debug for Block {
159
67
}
160
68
}
161
69
70
+ impl Default for Block {
71
+ fn default ( ) -> Self {
72
+ Self :: new ( )
73
+ }
74
+ }
75
+
76
+ /// A block device - a device which can read and write blocks (or
77
+ /// sectors). Only supports devices which are <= 2 TiB in size.
78
+ pub trait BlockDevice {
79
+ /// The errors that the `BlockDevice` can return. Must be debug formattable.
80
+ type Error : core:: fmt:: Debug ;
81
+ /// Read one or more blocks, starting at the given block index.
82
+ fn read ( & self , blocks : & mut [ Block ] , start_block_idx : BlockIdx ) -> Result < ( ) , Self :: Error > ;
83
+ /// Write one or more blocks, starting at the given block index.
84
+ fn write ( & self , blocks : & [ Block ] , start_block_idx : BlockIdx ) -> Result < ( ) , Self :: Error > ;
85
+ /// Determine how many blocks this device can hold.
86
+ fn num_blocks ( & self ) -> Result < BlockCount , Self :: Error > ;
87
+ }
88
+
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_idx = None ;
116
+ self . block_device . read ( & mut self . block , block_idx) ?;
117
+ self . block_idx = Some ( block_idx) ;
118
+ }
119
+ Ok ( & self . block [ 0 ] )
120
+ }
121
+
122
+ /// Read a block, and return a reference to it.
123
+ pub fn read_mut ( & mut self , block_idx : BlockIdx ) -> Result < & mut Block , D :: Error > {
124
+ if self . block_idx != Some ( block_idx) {
125
+ self . block_idx = None ;
126
+ self . block_device . read ( & mut self . block , block_idx) ?;
127
+ self . block_idx = Some ( block_idx) ;
128
+ }
129
+ Ok ( & mut self . block [ 0 ] )
130
+ }
131
+
132
+ /// Write back a block you read with [`Self::read_mut`] and then modified.
133
+ pub fn write_back ( & mut self ) -> Result < ( ) , D :: Error > {
134
+ self . block_device . write (
135
+ & self . block ,
136
+ self . block_idx . expect ( "write_back with no read" ) ,
137
+ )
138
+ }
139
+
140
+ /// Access a blank sector
141
+ pub fn blank_mut ( & mut self , block_idx : BlockIdx ) -> & mut Block {
142
+ self . block_idx = Some ( block_idx) ;
143
+ for b in self . block [ 0 ] . iter_mut ( ) {
144
+ * b = 0 ;
145
+ }
146
+ & mut self . block [ 0 ]
147
+ }
148
+
149
+ /// Access the block device
150
+ pub fn block_device ( & mut self ) -> & mut D {
151
+ // invalidate the cache
152
+ self . block_idx = None ;
153
+ // give them the block device
154
+ & mut self . block_device
155
+ }
156
+
157
+ /// Get the block device back
158
+ pub fn free ( self ) -> D {
159
+ self . block_device
160
+ }
161
+ }
162
+
163
+ /// The linear numeric address of a block (or sector).
164
+ ///
165
+ /// The first block on a disk gets `BlockIdx(0)` (which usually contains the
166
+ /// Master Boot Record).
167
+ #[ cfg_attr( feature = "defmt-log" , derive( defmt:: Format ) ) ]
168
+ #[ derive( Debug , Copy , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
169
+ pub struct BlockIdx ( pub u32 ) ;
170
+
162
171
impl BlockIdx {
163
172
/// Convert a block index into a 64-bit byte offset from the start of the
164
173
/// volume. Useful if your underlying block device actually works in
@@ -174,6 +183,65 @@ impl BlockIdx {
174
183
}
175
184
}
176
185
186
+ impl core:: ops:: Add < BlockCount > for BlockIdx {
187
+ type Output = BlockIdx ;
188
+ fn add ( self , rhs : BlockCount ) -> BlockIdx {
189
+ BlockIdx ( self . 0 + rhs. 0 )
190
+ }
191
+ }
192
+
193
+ impl core:: ops:: AddAssign < BlockCount > for BlockIdx {
194
+ fn add_assign ( & mut self , rhs : BlockCount ) {
195
+ self . 0 += rhs. 0
196
+ }
197
+ }
198
+
199
+ impl core:: ops:: Sub < BlockCount > for BlockIdx {
200
+ type Output = BlockIdx ;
201
+ fn sub ( self , rhs : BlockCount ) -> BlockIdx {
202
+ BlockIdx ( self . 0 - rhs. 0 )
203
+ }
204
+ }
205
+
206
+ impl core:: ops:: SubAssign < BlockCount > for BlockIdx {
207
+ fn sub_assign ( & mut self , rhs : BlockCount ) {
208
+ self . 0 -= rhs. 0
209
+ }
210
+ }
211
+
212
+ /// The a number of blocks (or sectors).
213
+ ///
214
+ /// Add this to a `BlockIdx` to get an actual address on disk.
215
+ #[ cfg_attr( feature = "defmt-log" , derive( defmt:: Format ) ) ]
216
+ #[ derive( Debug , Copy , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
217
+ pub struct BlockCount ( pub u32 ) ;
218
+
219
+ impl core:: ops:: Add < BlockCount > for BlockCount {
220
+ type Output = BlockCount ;
221
+ fn add ( self , rhs : BlockCount ) -> BlockCount {
222
+ BlockCount ( self . 0 + rhs. 0 )
223
+ }
224
+ }
225
+
226
+ impl core:: ops:: AddAssign < BlockCount > for BlockCount {
227
+ fn add_assign ( & mut self , rhs : BlockCount ) {
228
+ self . 0 += rhs. 0
229
+ }
230
+ }
231
+
232
+ impl core:: ops:: Sub < BlockCount > for BlockCount {
233
+ type Output = BlockCount ;
234
+ fn sub ( self , rhs : BlockCount ) -> BlockCount {
235
+ BlockCount ( self . 0 - rhs. 0 )
236
+ }
237
+ }
238
+
239
+ impl core:: ops:: SubAssign < BlockCount > for BlockCount {
240
+ fn sub_assign ( & mut self , rhs : BlockCount ) {
241
+ self . 0 -= rhs. 0
242
+ }
243
+ }
244
+
177
245
impl BlockCount {
178
246
/// How many blocks are required to hold this many bytes.
179
247
///
@@ -200,6 +268,12 @@ impl BlockCount {
200
268
}
201
269
}
202
270
271
+ /// An iterator returned from `Block::range`.
272
+ pub struct BlockIter {
273
+ inclusive_end : BlockIdx ,
274
+ current : BlockIdx ,
275
+ }
276
+
203
277
impl BlockIter {
204
278
/// Create a new `BlockIter`, from the given start block, through (and
205
279
/// including) the given end block.
0 commit comments