Skip to content

Commit 8a340f4

Browse files
committed
Add and use BlockCount and BlockIdx newtypes.
1 parent 025315a commit 8a340f4

File tree

2 files changed

+143
-31
lines changed

2 files changed

+143
-31
lines changed

src/block.rs

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
use core::ops::{Add, AddAssign, Sub, SubAssign};
2+
3+
/// A device which can read and write whole numbers of blocks.
4+
///
5+
/// Blocks are also referred to as sectors in some contexts.
6+
pub trait BlockDevice<const BLOCK_SIZE: usize = 512> {
7+
/// The error type returned by methods on this trait.
8+
type Error;
9+
10+
/// Returns the size of the device in blocks.
11+
fn block_count(&self) -> Result<BlockCount, Self::Error>;
12+
13+
/// Reads some number of blocks from the device, starting at `first_block_index`.
14+
///
15+
/// `first_block_index + blocks.len()` must not be greater than the size returned by
16+
/// `block_count`.
17+
fn read(
18+
&mut self,
19+
first_block_index: BlockIdx,
20+
blocks: &mut [[u8; BLOCK_SIZE]],
21+
) -> Result<(), Self::Error>;
22+
23+
/// Writes some number of blocks to the device, starting at `first_block_index`.
24+
///
25+
/// `first_block_index + blocks.len()` must not be greater than the size returned by
26+
/// `block_count`.
27+
fn write(
28+
&mut self,
29+
first_block_index: BlockIdx,
30+
blocks: &[[u8; BLOCK_SIZE]],
31+
) -> Result<(), Self::Error>;
32+
}
33+
34+
/// The linear numeric address of a block (or sector).
35+
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
36+
pub struct BlockIdx(pub u64);
37+
38+
impl BlockIdx {
39+
/// Creates an iterator from the current `BlockIdx` through the given number of blocks.
40+
pub fn range(self, num: BlockCount) -> BlockIter {
41+
BlockIter::new(self, self + BlockCount(num.0))
42+
}
43+
}
44+
45+
impl From<BlockIdx> for u64 {
46+
fn from(value: BlockIdx) -> Self {
47+
value.0.into()
48+
}
49+
}
50+
51+
impl Add<BlockCount> for BlockIdx {
52+
type Output = BlockIdx;
53+
54+
fn add(self, rhs: BlockCount) -> BlockIdx {
55+
BlockIdx(self.0 + rhs.0)
56+
}
57+
}
58+
59+
impl AddAssign<BlockCount> for BlockIdx {
60+
fn add_assign(&mut self, rhs: BlockCount) {
61+
self.0 += rhs.0
62+
}
63+
}
64+
65+
impl Sub<BlockCount> for BlockIdx {
66+
type Output = BlockIdx;
67+
68+
fn sub(self, rhs: BlockCount) -> BlockIdx {
69+
BlockIdx(self.0 - rhs.0)
70+
}
71+
}
72+
73+
impl SubAssign<BlockCount> for BlockIdx {
74+
fn sub_assign(&mut self, rhs: BlockCount) {
75+
self.0 -= rhs.0
76+
}
77+
}
78+
79+
/// A number of blocks (or sectors).
80+
///
81+
/// This may be added to a [`BlockIdx`] to get another `BlockIdx`.
82+
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
83+
pub struct BlockCount(pub u64);
84+
85+
impl Add<BlockCount> for BlockCount {
86+
type Output = BlockCount;
87+
88+
fn add(self, rhs: BlockCount) -> BlockCount {
89+
BlockCount(self.0 + rhs.0)
90+
}
91+
}
92+
93+
impl AddAssign<BlockCount> for BlockCount {
94+
fn add_assign(&mut self, rhs: BlockCount) {
95+
self.0 += rhs.0
96+
}
97+
}
98+
99+
impl Sub<BlockCount> for BlockCount {
100+
type Output = BlockCount;
101+
102+
fn sub(self, rhs: BlockCount) -> BlockCount {
103+
BlockCount(self.0 - rhs.0)
104+
}
105+
}
106+
107+
impl SubAssign<BlockCount> for BlockCount {
108+
fn sub_assign(&mut self, rhs: BlockCount) {
109+
self.0 -= rhs.0
110+
}
111+
}
112+
113+
/// An iterator returned from `Block::range`.
114+
pub struct BlockIter {
115+
inclusive_end: BlockIdx,
116+
current: BlockIdx,
117+
}
118+
119+
impl BlockIter {
120+
/// Creates a new `BlockIter`, from the given start block, through (and including) the given end
121+
/// block.
122+
pub const fn new(start: BlockIdx, inclusive_end: BlockIdx) -> BlockIter {
123+
BlockIter {
124+
inclusive_end,
125+
current: start,
126+
}
127+
}
128+
}
129+
130+
impl Iterator for BlockIter {
131+
type Item = BlockIdx;
132+
fn next(&mut self) -> Option<Self::Item> {
133+
if self.current.0 >= self.inclusive_end.0 {
134+
None
135+
} else {
136+
let this = self.current;
137+
self.current += BlockCount(1);
138+
Some(this)
139+
}
140+
}
141+
}

src/lib.rs

+2-31
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#![deny(missing_docs)]
99
#![deny(unsafe_code)]
1010

11+
/// Types and traits for block devices.
12+
pub mod block;
1113
/// Currently contains [`OverlapIterator`]
1214
pub mod iter;
1315
/// Technology specific traits for NOR Flashes
@@ -53,34 +55,3 @@ pub trait Storage: ReadStorage {
5355
/// and might as such do RMW operations at an undesirable performance impact.
5456
fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error>;
5557
}
56-
57-
/// A device which can read and write whole numbers of blocks.
58-
///
59-
/// Blocks are also referred to as sectors in some contexts.
60-
pub trait BlockDevice<const BLOCK_SIZE: usize = 512> {
61-
/// The error type returned by methods on this trait.
62-
type Error;
63-
64-
/// Returns the size of the device in blocks.
65-
fn block_count(&self) -> Result<u64, Self::Error>;
66-
67-
/// Reads some number of blocks from the device, starting at `first_block_index`.
68-
///
69-
/// `first_block_index + blocks.len()` must not be greater than the size returned by
70-
/// `block_count`.
71-
fn read(
72-
&mut self,
73-
first_block_index: u64,
74-
blocks: &mut [[u8; BLOCK_SIZE]],
75-
) -> Result<(), Self::Error>;
76-
77-
/// Writes some number of blocks to the device, starting at `first_block_index`.
78-
///
79-
/// `first_block_index + blocks.len()` must not be greater than the size returned by
80-
/// `block_count`.
81-
fn write(
82-
&mut self,
83-
first_block_index: u64,
84-
blocks: &[[u8; BLOCK_SIZE]],
85-
) -> Result<(), Self::Error>;
86-
}

0 commit comments

Comments
 (0)