3
3
//! Generic code for handling block devices, such as types for identifying
4
4
//! a particular block on a block device by its index.
5
5
6
+ use embedded_storage:: BlockDevice ;
7
+
6
8
/// A standard 512 byte block (also known as a sector).
7
9
///
8
10
/// IBM PC formatted 5.25" and 3.5" floppy disks, IDE/SATA Hard Drives up to
9
11
/// about 2 TiB, and almost all SD/MMC cards have 512 byte blocks.
10
12
///
11
13
/// This library does not support devices with a block size other than 512
12
14
/// bytes.
13
- #[ derive( Clone ) ]
14
- pub struct Block {
15
- /// The 512 bytes in this block (or sector).
16
- pub contents : [ u8 ; Block :: LEN ] ,
17
- }
15
+ pub type Block = [ u8 ; BLOCK_LEN ] ;
18
16
19
- impl Block {
20
- /// All our blocks are a fixed length of 512 bytes. We do not support
21
- /// 'Advanced Format' Hard Drives with 4 KiB blocks, nor weird old
22
- /// pre-3.5-inch floppy disk formats.
23
- pub const LEN : usize = 512 ;
17
+ /// All our blocks are a fixed length of 512 bytes. We do not support
18
+ /// 'Advanced Format' Hard Drives with 4 KiB blocks, nor weird old
19
+ /// pre-3.5-inch floppy disk formats.
20
+ pub const BLOCK_LEN : usize = 512 ;
24
21
25
- /// Sometimes we want `LEN` as a `u32` and the casts don't look nice.
26
- pub const LEN_U32 : u32 = 512 ;
22
+ /// Sometimes we want `LEN` as a `u32` and the casts don't look nice.
23
+ pub const BLOCK_LEN_U32 : u32 = 512 ;
27
24
28
- /// Create a new block full of zeros.
29
- pub fn new ( ) -> Block {
30
- Block {
31
- contents : [ 0u8 ; Self :: LEN ] ,
32
- }
33
- }
34
- }
35
-
36
- impl core:: ops:: Deref for Block {
37
- type Target = [ u8 ; 512 ] ;
38
- fn deref ( & self ) -> & [ u8 ; 512 ] {
39
- & self . contents
40
- }
41
- }
42
-
43
- impl core:: ops:: DerefMut for Block {
44
- fn deref_mut ( & mut self ) -> & mut [ u8 ; 512 ] {
45
- & mut self . contents
46
- }
47
- }
48
-
49
- impl core:: fmt:: Debug for Block {
50
- fn fmt ( & self , fmt : & mut core:: fmt:: Formatter ) -> core:: fmt:: Result {
51
- writeln ! ( fmt, "Block:" ) ?;
52
- for line in self . contents . chunks ( 32 ) {
53
- for b in line {
54
- write ! ( fmt, "{:02x}" , b) ?;
55
- }
56
- write ! ( fmt, " " ) ?;
57
- for & b in line {
58
- if ( 0x20 ..=0x7F ) . contains ( & b) {
59
- write ! ( fmt, "{}" , b as char ) ?;
60
- } else {
61
- write ! ( fmt, "." ) ?;
62
- }
63
- }
64
- writeln ! ( fmt) ?;
65
- }
66
- Ok ( ( ) )
67
- }
68
- }
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
- }
25
+ /// Sometimes we want `LEN` as a `u64` and the casts don't look nice.
26
+ pub const BLOCK_LEN_U64 : u64 = 512 ;
88
27
89
28
/// A caching layer for block devices
90
29
///
@@ -93,7 +32,7 @@ pub trait BlockDevice {
93
32
pub struct BlockCache < D > {
94
33
block_device : D ,
95
34
block : [ Block ; 1 ] ,
96
- block_idx : Option < BlockIdx > ,
35
+ block_idx : Option < u64 > ,
97
36
}
98
37
99
38
impl < D > BlockCache < D >
@@ -104,26 +43,26 @@ where
104
43
pub fn new ( block_device : D ) -> BlockCache < D > {
105
44
BlockCache {
106
45
block_device,
107
- block : [ Block :: new ( ) ] ,
46
+ block : [ [ 0 ; BLOCK_LEN ] ] ,
108
47
block_idx : None ,
109
48
}
110
49
}
111
50
112
51
/// Read a block, and return a reference to it.
113
- pub fn read ( & mut self , block_idx : BlockIdx ) -> Result < & Block , D :: Error > {
52
+ pub fn read ( & mut self , block_idx : u64 ) -> Result < & Block , D :: Error > {
114
53
if self . block_idx != Some ( block_idx) {
115
54
self . block_idx = None ;
116
- self . block_device . read ( & mut self . block , block_idx ) ?;
55
+ self . block_device . read ( block_idx , & mut self . block ) ?;
117
56
self . block_idx = Some ( block_idx) ;
118
57
}
119
58
Ok ( & self . block [ 0 ] )
120
59
}
121
60
122
61
/// Read a block, and return a reference to it.
123
- pub fn read_mut ( & mut self , block_idx : BlockIdx ) -> Result < & mut Block , D :: Error > {
62
+ pub fn read_mut ( & mut self , block_idx : u64 ) -> Result < & mut Block , D :: Error > {
124
63
if self . block_idx != Some ( block_idx) {
125
64
self . block_idx = None ;
126
- self . block_device . read ( & mut self . block , block_idx ) ?;
65
+ self . block_device . read ( block_idx , & mut self . block ) ?;
127
66
self . block_idx = Some ( block_idx) ;
128
67
}
129
68
Ok ( & mut self . block [ 0 ] )
@@ -132,13 +71,13 @@ where
132
71
/// Write back a block you read with [`Self::read_mut`] and then modified.
133
72
pub fn write_back ( & mut self ) -> Result < ( ) , D :: Error > {
134
73
self . block_device . write (
135
- & self . block ,
136
74
self . block_idx . expect ( "write_back with no read" ) ,
75
+ & self . block ,
137
76
)
138
77
}
139
78
140
79
/// Access a blank sector
141
- pub fn blank_mut ( & mut self , block_idx : BlockIdx ) -> & mut Block {
80
+ pub fn blank_mut ( & mut self , block_idx : u64 ) -> & mut Block {
142
81
self . block_idx = Some ( block_idx) ;
143
82
for b in self . block [ 0 ] . iter_mut ( ) {
144
83
* b = 0 ;
@@ -173,7 +112,7 @@ impl BlockIdx {
173
112
/// volume. Useful if your underlying block device actually works in
174
113
/// bytes, like `open("/dev/mmcblk0")` does on Linux.
175
114
pub fn into_bytes ( self ) -> u64 {
176
- ( u64:: from ( self . 0 ) ) * ( Block :: LEN as u64 )
115
+ u64:: from ( self . 0 ) * BLOCK_LEN_U64
177
116
}
178
117
179
118
/// Create an iterator from the current `BlockIdx` through the given
@@ -183,6 +122,12 @@ impl BlockIdx {
183
122
}
184
123
}
185
124
125
+ impl From < BlockIdx > for u64 {
126
+ fn from ( value : BlockIdx ) -> Self {
127
+ value. 0 . into ( )
128
+ }
129
+ }
130
+
186
131
impl core:: ops:: Add < BlockCount > for BlockIdx {
187
132
type Output = BlockIdx ;
188
133
fn add ( self , rhs : BlockCount ) -> BlockIdx {
@@ -254,8 +199,8 @@ impl BlockCount {
254
199
/// assert_eq!(BlockCount::from_bytes(1025), BlockCount(3));
255
200
/// ```
256
201
pub const fn from_bytes ( byte_count : u32 ) -> BlockCount {
257
- let mut count = byte_count / Block :: LEN_U32 ;
258
- if ( count * Block :: LEN_U32 ) != byte_count {
202
+ let mut count = byte_count / BLOCK_LEN_U32 ;
203
+ if ( count * BLOCK_LEN_U32 ) != byte_count {
259
204
count += 1 ;
260
205
}
261
206
BlockCount ( count)
@@ -264,7 +209,7 @@ impl BlockCount {
264
209
/// Take a number of blocks and increment by the integer number of blocks
265
210
/// required to get to the block that holds the byte at the given offset.
266
211
pub fn offset_bytes ( self , offset : u32 ) -> Self {
267
- BlockCount ( self . 0 + ( offset / Block :: LEN_U32 ) )
212
+ BlockCount ( self . 0 + ( offset / BLOCK_LEN_U32 ) )
268
213
}
269
214
}
270
215
0 commit comments