Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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