Skip to content

Commit

Permalink
fix: get rid of controlflow
Browse files Browse the repository at this point in the history
  • Loading branch information
lulf committed Jan 9, 2024
1 parent b29e70d commit b880f40
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 51 deletions.
30 changes: 11 additions & 19 deletions src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
//!

use core::num::NonZeroU32;
use core::ops::ControlFlow;
use core::ops::Range;

use embedded_storage_async::nor_flash::{MultiwriteNorFlash, NorFlash};
Expand Down Expand Up @@ -289,7 +288,7 @@ pub async fn find_next_free_item_spot<S: NorFlash>(
data_length: u32,
) -> Result<Option<u32>, Error<S::Error>> {
let (_, free_item_address) = ItemHeaderIter::new(start_address, end_address)
.traverse(flash, |_, _| ControlFlow::Continue(()))
.traverse(flash, |_, _| true)
.await?;
if let Some(available) = ItemHeader::available_data_bytes::<S>(end_address - free_item_address)
{
Expand Down Expand Up @@ -423,10 +422,7 @@ pub async fn is_page_empty<S: NorFlash>(

Ok(
ItemHeaderIter::new(page_data_start_address, page_data_end_address)
.traverse(flash, |header, _| match header.crc {
Some(_) => ControlFlow::Break(()),
None => ControlFlow::Continue(()),
})
.traverse(flash, |header, _| header.crc.is_none())
.await?
.0
.is_none(),
Expand Down Expand Up @@ -498,32 +494,28 @@ impl ItemHeaderIter {
&mut self,
flash: &mut S,
) -> Result<(Option<ItemHeader>, u32), Error<S::Error>> {
self.traverse(flash, |_, _| ControlFlow::Break(())).await
self.traverse(flash, |_, _| false).await
}

/// Traverse headers until the callback returns `Break`. If the callback returns `Continue`,
/// Traverse headers until the callback returns false. If the callback returns true,
/// the element is skipped and traversal continues.
///
/// If the end of the headers is reached, a `None` item header is returned.
pub async fn traverse<S: NorFlash>(
&mut self,
flash: &mut S,
callback: impl Fn(&ItemHeader, u32) -> ControlFlow<(), ()>,
callback: impl Fn(&ItemHeader, u32) -> bool,
) -> Result<(Option<ItemHeader>, u32), Error<S::Error>> {
loop {
match ItemHeader::read_new(flash, self.current_address, self.end_address).await {
Ok(Some(header)) => {
let next_address = header.next_item_address::<S>(self.current_address);
match callback(&header, self.current_address) {
ControlFlow::Continue(_) => {
self.current_address = next_address;
continue;
}
ControlFlow::Break(_) => {
let current_address = self.current_address;
self.current_address = next_address;
return Ok((Some(header), current_address));
}
if callback(&header, self.current_address) {
self.current_address = next_address;
} else {
let current_address = self.current_address;
self.current_address = next_address;
return Ok((Some(header), current_address));
}
}
Ok(None) => {
Expand Down
20 changes: 1 addition & 19 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

use core::{
fmt::Debug,
ops::{ControlFlow, Deref, DerefMut, Range},
ops::{Deref, DerefMut, Range},
};
use embedded_storage_async::nor_flash::NorFlash;

Expand Down Expand Up @@ -377,24 +377,6 @@ impl<S: NorFlash> NorFlashExt for S {
};
}

/// Some plumbing for things not yet stable in std/core
trait ResultToControlflow<B, C> {
fn to_controlflow(self) -> ControlFlow<B, C>;
}

impl<B, C, E> ResultToControlflow<B, C> for Result<C, E>
where
// T: Into<C>,
E: Into<B>,
{
fn to_controlflow(self) -> ControlFlow<B, C> {
match self {
Ok(c) => ControlFlow::Continue(c),
Err(b) => ControlFlow::Break(b.into()),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
7 changes: 2 additions & 5 deletions src/mock_flash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ impl<const PAGES: usize, const BYTES_PER_WORD: usize, const PAGE_WORDS: usize>

let mut it = crate::item::ItemHeaderIter::new(page_data_start, page_data_end);
while let (Some(header), item_address) =
block_on(it.traverse(self, |_, _| core::ops::ControlFlow::Break(()))).unwrap()
block_on(it.traverse(self, |_, _| false)).unwrap()
{
let next_item_address = header.next_item_address::<Self>(item_address);
let maybe_item =
Expand All @@ -163,8 +163,6 @@ impl<const PAGES: usize, const BYTES_PER_WORD: usize, const PAGE_WORDS: usize>
/// - If true, the item is present and fine.
/// - If false, the item is corrupt or erased.
pub fn get_item_presence(&mut self, target_item_address: u32) -> Option<bool> {
use core::ops::ControlFlow;

use crate::NorFlashExt;
use futures::executor::block_on;

Expand All @@ -186,8 +184,7 @@ impl<const PAGES: usize, const BYTES_PER_WORD: usize, const PAGE_WORDS: usize>

let mut found_item = None;
let mut it = crate::item::ItemHeaderIter::new(page_data_start, page_data_end);
while let (Some(header), item_address) =
block_on(it.traverse(self, |_, _| ControlFlow::Break(()))).unwrap()
while let (Some(header), item_address) = block_on(it.traverse(self, |_, _| false)).unwrap()
{
let next_item_address = header.next_item_address::<Self>(item_address);

Expand Down
10 changes: 2 additions & 8 deletions src/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,13 +375,7 @@ impl<'d, S: NorFlash> QueueIterator<'d, S> {
// Search for the first item with data
let mut it = ItemHeaderIter::new(current_address, page_data_end_address);
if let (Some(found_item_header), found_item_address) = it
.traverse(self.flash, |header, _| {
if header.crc.is_some() {
ControlFlow::Break(())
} else {
ControlFlow::Continue(())
}
})
.traverse(self.flash, |header, _| header.crc.is_none())
.await?
{
let maybe_item = found_item_header
Expand Down Expand Up @@ -477,7 +471,7 @@ pub async fn find_max_fit<S: NorFlash>(
calculate_page_end_address::<S>(flash_range.clone(), current_page) - S::WORD_SIZE as u32;

let next_item_address = ItemHeaderIter::new(page_data_start_address, page_data_end_address)
.traverse(flash, |_, _| ControlFlow::Continue(()))
.traverse(flash, |_, _| true)
.await?
.1;

Expand Down

0 comments on commit b880f40

Please sign in to comment.