Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add BlockDevice trait. #59

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

include:
# Test MSRV
- rust: 1.50.0
- rust: 1.60.0
TARGET: x86_64-unknown-linux-gnu

# Test nightly but don't fail
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

- Add `start()` and `end()` method to the `Region` trait.
- Much faster `OverlapIterator`.
- Add `BlockDevice` trait, along with `BlockIdx` and `BlockCount` types.

## [0.3.1] - 2023-12-04

Expand Down
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,10 @@ documentation = "https://docs.rs/embedded-storage"
readme = "README.md"
keywords = ["storage"]
categories = ["embedded", "hardware-support", "no-std"]

[dependencies]
defmt = { version = "0.3.8", optional = true }

[features]
default = []
defmt = ["dep:defmt"]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ These issues / PRs will be labeled as `proposal`s in the issue tracker.

## Minimum Supported Rust Version (MSRV)

This crate is guaranteed to compile on stable Rust 1.50.0 and up. It *might*
This crate is guaranteed to compile on stable Rust 1.60.0 and up. It _might_
compile with older versions but that may change in any new patch release.

## License
Expand Down
143 changes: 143 additions & 0 deletions src/block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
use core::ops::{Add, AddAssign, Sub, SubAssign};

/// A device which can read and write whole numbers of blocks.
///
/// Blocks are also referred to as sectors in some contexts.
pub trait BlockDevice<const BLOCK_SIZE: usize = 512> {
/// The error type returned by methods on this trait.
type Error;

/// Returns the size of the device in blocks.
fn block_count(&self) -> Result<BlockCount, Self::Error>;

/// Reads some number of blocks from the device, starting at `first_block_index`.
///
/// `first_block_index + blocks.len()` must not be greater than the size returned by
/// `block_count`.
fn read(
&mut self,
blocks: &mut [[u8; BLOCK_SIZE]],
first_block_index: BlockIdx,
) -> Result<(), Self::Error>;

/// Writes some number of blocks to the device, starting at `first_block_index`.
///
/// `first_block_index + blocks.len()` must not be greater than the size returned by
/// `block_count`.
fn write(
&mut self,
blocks: &[[u8; BLOCK_SIZE]],
first_block_index: BlockIdx,
) -> Result<(), Self::Error>;
}

/// The linear numeric address of a block (or sector).
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct BlockIdx(pub u64);

impl BlockIdx {
/// Creates an iterator from the current `BlockIdx` through the given number of blocks.
pub fn range(self, num: BlockCount) -> BlockIter {
BlockIter::new(self, self + BlockCount(num.0))
}
}

impl From<BlockIdx> for u64 {
fn from(value: BlockIdx) -> Self {
value.0.into()
}
}

impl Add<BlockCount> for BlockIdx {
type Output = BlockIdx;

fn add(self, rhs: BlockCount) -> BlockIdx {
BlockIdx(self.0 + rhs.0)
}
}

impl AddAssign<BlockCount> for BlockIdx {
fn add_assign(&mut self, rhs: BlockCount) {
self.0 += rhs.0
}
}

impl Sub<BlockCount> for BlockIdx {
type Output = BlockIdx;

fn sub(self, rhs: BlockCount) -> BlockIdx {
BlockIdx(self.0 - rhs.0)
}
}

impl SubAssign<BlockCount> for BlockIdx {
fn sub_assign(&mut self, rhs: BlockCount) {
self.0 -= rhs.0
}
}

/// A number of blocks (or sectors).
///
/// This may be added to a [`BlockIdx`] to get another `BlockIdx`.
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct BlockCount(pub u64);

impl Add<BlockCount> for BlockCount {
type Output = BlockCount;

fn add(self, rhs: BlockCount) -> BlockCount {
BlockCount(self.0 + rhs.0)
}
}

impl AddAssign<BlockCount> for BlockCount {
fn add_assign(&mut self, rhs: BlockCount) {
self.0 += rhs.0
}
}

impl Sub<BlockCount> for BlockCount {
type Output = BlockCount;

fn sub(self, rhs: BlockCount) -> BlockCount {
BlockCount(self.0 - rhs.0)
}
}

impl SubAssign<BlockCount> for BlockCount {
fn sub_assign(&mut self, rhs: BlockCount) {
self.0 -= rhs.0
}
}

/// An iterator returned from `Block::range`.
pub struct BlockIter {
inclusive_end: BlockIdx,
current: BlockIdx,
}

impl BlockIter {
/// Creates a new `BlockIter`, from the given start block, through (and including) the given end
/// block.
pub const fn new(start: BlockIdx, inclusive_end: BlockIdx) -> BlockIter {
BlockIter {
inclusive_end,
current: start,
}
}
}

impl 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)
}
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#![deny(missing_docs)]
#![deny(unsafe_code)]

/// Types and traits for block devices.
pub mod block;
/// Currently contains [`OverlapIterator`]
pub mod iter;
/// Technology specific traits for NOR Flashes
Expand Down
Loading