Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Relax the MultiwriteNorFlash to only need clearing of words
Browse files Browse the repository at this point in the history
korken89 committed Aug 4, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 163dfc5 commit 798be4f
Showing 8 changed files with 126 additions and 95 deletions.
4 changes: 2 additions & 2 deletions src/cache/mod.rs
Original file line number Diff line number Diff line change
@@ -96,7 +96,7 @@ pub(crate) trait PrivateCacheImpl: Invalidate {
&mut self,
flash_range: Range<u32>,
item_address: u32,
item_header: &ItemHeader,
item_header: &ItemHeader<S>,
) {
self.mark_dirty();
self.page_pointers()
@@ -108,7 +108,7 @@ pub(crate) trait PrivateCacheImpl: Invalidate {
&mut self,
flash_range: Range<u32>,
item_address: u32,
item_header: &ItemHeader,
item_header: &ItemHeader<S>,
) {
self.mark_dirty();
self.page_pointers()
16 changes: 8 additions & 8 deletions src/cache/page_pointers.rs
Original file line number Diff line number Diff line change
@@ -14,13 +14,13 @@ pub(crate) trait PagePointersCache: Debug {
&mut self,
flash_range: Range<u32>,
item_address: u32,
item_header: &ItemHeader,
item_header: &ItemHeader<S>,
);
fn notice_item_erased<S: NorFlash>(
&mut self,
flash_range: Range<u32>,
item_address: u32,
item_header: &ItemHeader,
item_header: &ItemHeader<S>,
);

fn notice_page_state(&mut self, page_index: usize, new_state: PageState);
@@ -89,11 +89,11 @@ impl<const PAGE_COUNT: usize> PagePointersCache for CachedPagePointers<PAGE_COUN
&mut self,
flash_range: Range<u32>,
item_address: u32,
item_header: &ItemHeader,
item_header: &ItemHeader<S>,
) {
let page_index = calculate_page_index::<S>(flash_range, item_address);

let next_item_address = item_header.next_item_address::<S>(item_address);
let next_item_address = item_header.next_item_address(item_address);

// We only care about the furthest written item, so discard if this is an earlier item
if let Some(first_item_after_written) = self.first_item_after_written(page_index) {
@@ -109,7 +109,7 @@ impl<const PAGE_COUNT: usize> PagePointersCache for CachedPagePointers<PAGE_COUN
&mut self,
flash_range: Range<u32>,
item_address: u32,
item_header: &ItemHeader,
item_header: &ItemHeader<S>,
) {
let page_index = calculate_page_index::<S>(flash_range.clone(), item_address);

@@ -120,7 +120,7 @@ impl<const PAGE_COUNT: usize> PagePointersCache for CachedPagePointers<PAGE_COUN

if item_address == next_unerased_item {
self.after_erased_pointers[page_index] =
NonZeroU32::new(item_header.next_item_address::<S>(item_address));
NonZeroU32::new(item_header.next_item_address(item_address));
}
}

@@ -155,15 +155,15 @@ impl PagePointersCache for UncachedPagePointers {
&mut self,
_flash_range: Range<u32>,
_item_address: u32,
_item_header: &ItemHeader,
_item_header: &ItemHeader<S>,
) {
}

fn notice_item_erased<S: NorFlash>(
&mut self,
_flash_range: Range<u32>,
_item_address: u32,
_item_header: &ItemHeader,
_item_header: &ItemHeader<S>,
) {
}

6 changes: 3 additions & 3 deletions src/cache/tests.rs
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ mod queue_tests {
reads: 594934,
writes: 6299,
bytes_read: 2766058,
bytes_written: 53299
bytes_written: 45299,
}
);
}
@@ -37,7 +37,7 @@ mod queue_tests {
reads: 308740,
writes: 6299,
bytes_read: 2479864,
bytes_written: 53299
bytes_written: 45299
}
);
}
@@ -51,7 +51,7 @@ mod queue_tests {
reads: 211172,
writes: 6299,
bytes_read: 1699320,
bytes_written: 53299
bytes_written: 45299
}
);
}
155 changes: 91 additions & 64 deletions src/item.rs
Original file line number Diff line number Diff line change
@@ -6,10 +6,12 @@
//! ```text
//! ┌──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
//! │ : : : │ : │ : │ : : : : : │ : : : : : : : : : │ : : : : : │
//! │ CRC │ Length │ Length' │Pad to word align│ Data │Pad to word align│
//! │ CRC ... │ Length │ Length' │Pad to word align│ Data │Pad to word align│
//! │ : : : │ : │ : │ : : : : : │ : : : : : : : : : │ : : : : : │
//! └──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴───┴──┴──┴──┴─┴──┴──┴──┴──┴──┴──┘
//! 0 1 2 3 4 5 6 7 8 8+padding 8+padding+length 8+padding+length+endpadding
//! 0 1 2 3 ... WS WS+2 WS+4 WS+4+padding WS+4+padding+length WS+4+padding+length+endpadding
//!
//! WS = max(4, WORD_SIZE)
//! ```
//!
//! An item consists of an [ItemHeader] and some data.
@@ -21,36 +23,42 @@
//! and has some other modifications to make corruption less likely to happen.
//!
use core::num::NonZeroU32;
use core::ops::Range;
use core::{marker::PhantomData, num::NonZeroU32};

use embedded_storage_async::nor_flash::{MultiwriteNorFlash, NorFlash};
use embedded_storage_async::nor_flash::NorFlash;

use crate::{
cache::PrivateCacheImpl, calculate_page_address, calculate_page_end_address,
calculate_page_index, get_page_state, round_down_to_alignment, round_down_to_alignment_usize,
round_up_to_alignment, round_up_to_alignment_usize, AlignedBuf, Error, NorFlashExt, PageState,
MAX_WORD_SIZE,
WordclearNorFlash, MAX_WORD_SIZE,
};

#[derive(Debug, Clone)]
pub struct ItemHeader {
pub struct ItemHeader<S> {
/// Length of the item payload (so not including the header and not including word alignment)
pub length: u16,
pub crc: Option<NonZeroU32>,
_p: PhantomData<S>,
}

impl ItemHeader {
const LENGTH: usize = 8;
impl<S: NorFlash> ItemHeader<S> {
const DATA_CRC_LENGTH: usize = if <S as NorFlashExt>::WORD_SIZE < 4 {
4 // The minimum is 4 to hold the CRC32.
} else {
<S as NorFlashExt>::WORD_SIZE
};
const LENGTH: usize = Self::DATA_CRC_LENGTH + 4;

const DATA_CRC_FIELD: Range<usize> = 0..4;
const LENGTH_FIELD: Range<usize> = 4..6;
const LENGTH_CRC_FIELD: Range<usize> = 6..8;
const DATA_CRC_FIELD: Range<usize> = 0..Self::DATA_CRC_LENGTH;
const LENGTH_FIELD: Range<usize> = Self::DATA_CRC_LENGTH..Self::DATA_CRC_LENGTH + 2;
const LENGTH_CRC_FIELD: Range<usize> = Self::DATA_CRC_LENGTH + 2..Self::DATA_CRC_LENGTH + 4;

/// Read the header from the flash at the given address.
///
/// If the item doesn't exist or doesn't fit between the address and the end address, none is returned.
pub async fn read_new<S: NorFlash>(
pub async fn read_new(
flash: &mut S,
address: u32,
end_address: u32,
@@ -90,25 +98,28 @@ impl ItemHeader {
Ok(Some(Self {
length: u16::from_le_bytes(header_slice[Self::LENGTH_FIELD].try_into().unwrap()),
crc: {
match u32::from_le_bytes(header_slice[Self::DATA_CRC_FIELD].try_into().unwrap()) {
match u32::from_le_bytes(
header_slice[Self::DATA_CRC_FIELD][..4].try_into().unwrap(),
) {
0 => None,
value => Some(NonZeroU32::new(value).unwrap()),
}
},
_p: PhantomData,
}))
}

pub async fn read_item<'d, S: NorFlash>(
pub async fn read_item<'d>(
self,
flash: &mut S,
data_buffer: &'d mut [u8],
address: u32,
end_address: u32,
) -> Result<MaybeItem<'d>, Error<S::Error>> {
) -> Result<MaybeItem<'d, S>, Error<S::Error>> {
match self.crc {
None => Ok(MaybeItem::Erased(self, data_buffer)),
Some(header_crc) => {
let data_address = ItemHeader::data_address::<S>(address);
let data_address = Self::data_address(address);
let read_len = round_up_to_alignment_usize::<S>(self.length as usize);
if data_buffer.len() < read_len {
return Err(Error::BufferTooSmall(read_len));
@@ -141,7 +152,7 @@ impl ItemHeader {
}
}

async fn write<S: NorFlash>(&self, flash: &mut S, address: u32) -> Result<(), Error<S::Error>> {
async fn write(&self, flash: &mut S, address: u32) -> Result<(), Error<S::Error>> {
let mut buffer = AlignedBuf([0xFF; MAX_WORD_SIZE]);

buffer[Self::DATA_CRC_FIELD]
@@ -163,47 +174,62 @@ impl ItemHeader {
})
}

/// Erase this item by setting the crc to none and overwriting the header with it
pub async fn erase_data<S: MultiwriteNorFlash>(
mut self,
flash: &mut S,
flash_range: Range<u32>,
cache: &mut impl PrivateCacheImpl,
address: u32,
) -> Result<Self, Error<S::Error>> {
self.crc = None;
cache.notice_item_erased::<S>(flash_range.clone(), address, &self);
self.write(flash, address).await?;
Ok(self)
async fn clear_data_crc(&self, flash: &mut S, address: u32) -> Result<(), Error<S::Error>> {
let buffer = AlignedBuf([0x0; MAX_WORD_SIZE]);

flash
.write(address, &buffer[Self::DATA_CRC_FIELD])
.await
.map_err(|e| Error::Storage {
value: e,
#[cfg(feature = "_test")]
backtrace: std::backtrace::Backtrace::capture(),
})
}

/// Get the address of the start of the data for this item
pub const fn data_address<S: NorFlash>(address: u32) -> u32 {
pub const fn data_address(address: u32) -> u32 {
address + round_up_to_alignment::<S>(Self::LENGTH as u32)
}

/// Get the location of the next item in flash
pub const fn next_item_address<S: NorFlash>(&self, address: u32) -> u32 {
let data_address = ItemHeader::data_address::<S>(address);
pub const fn next_item_address(&self, address: u32) -> u32 {
let data_address = Self::data_address(address);
data_address + round_up_to_alignment::<S>(self.length as u32)
}

/// Calculates the amount of bytes available for data.
/// Essentially, it's the given amount minus the header and minus some alignment padding.
pub const fn available_data_bytes<S: NorFlash>(total_available: u32) -> Option<u32> {
let data_start = Self::data_address::<S>(0);
pub const fn available_data_bytes(total_available: u32) -> Option<u32> {
let data_start = Self::data_address(0);
let data_end = round_down_to_alignment::<S>(total_available);

data_end.checked_sub(data_start)
}
}

pub struct Item<'d> {
pub header: ItemHeader,
impl<S: WordclearNorFlash> ItemHeader<S> {
/// Erase this item by setting the crc to none and overwriting the header with it
pub async fn erase_data(
mut self,
flash: &mut S,
flash_range: Range<u32>,
cache: &mut impl PrivateCacheImpl,
address: u32,
) -> Result<Self, Error<S::Error>> {
self.crc = None;
cache.notice_item_erased::<S>(flash_range.clone(), address, &self);
self.clear_data_crc(flash, address).await?;
Ok(self)
}
}

pub struct Item<'d, S> {
pub header: ItemHeader<S>,
data_buffer: &'d mut [u8],
}

impl<'d> Item<'d> {
impl<'d, S: NorFlash> Item<'d, S> {
pub fn data(&self) -> &[u8] {
&self.data_buffer[..self.header.length as usize]
}
@@ -213,32 +239,33 @@ impl<'d> Item<'d> {
}

/// Destruct the item to get back the full data buffer
pub fn destruct(self) -> (ItemHeader, &'d mut [u8]) {
pub fn destruct(self) -> (ItemHeader<S>, &'d mut [u8]) {
(self.header, self.data_buffer)
}

pub async fn write_new<S: NorFlash>(
pub async fn write_new(
flash: &mut S,
flash_range: Range<u32>,
cache: &mut impl PrivateCacheImpl,
address: u32,
data: &'d [u8],
) -> Result<ItemHeader, Error<S::Error>> {
) -> Result<ItemHeader<S>, Error<S::Error>> {
let header = ItemHeader {
length: data.len() as u16,
crc: Some(adapted_crc32(data)),
_p: PhantomData,
};

Self::write_raw(flash, flash_range, cache, &header, data, address).await?;

Ok(header)
}

async fn write_raw<S: NorFlash>(
async fn write_raw(
flash: &mut S,
flash_range: Range<u32>,
cache: &mut impl PrivateCacheImpl,
header: &ItemHeader,
header: &ItemHeader<S>,
data: &[u8],
address: u32,
) -> Result<(), Error<S::Error>> {
@@ -247,7 +274,7 @@ impl<'d> Item<'d> {

let (data_block, data_left) = data.split_at(round_down_to_alignment_usize::<S>(data.len()));

let data_address = ItemHeader::data_address::<S>(address);
let data_address = ItemHeader::<S>::data_address(address);
flash
.write(data_address, data_block)
.await
@@ -276,7 +303,7 @@ impl<'d> Item<'d> {
Ok(())
}

pub async fn write<S: NorFlash>(
pub async fn write(
&self,
flash: &mut S,
flash_range: Range<u32>,
@@ -294,15 +321,15 @@ impl<'d> Item<'d> {
.await
}

pub fn unborrow(self) -> ItemUnborrowed {
pub fn unborrow(self) -> ItemUnborrowed<S> {
ItemUnborrowed {
header: self.header,
data_buffer_len: self.data_buffer.len(),
}
}
}

impl<'d> core::fmt::Debug for Item<'d> {
impl<'d, S: core::fmt::Debug> core::fmt::Debug for Item<'d, S> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Item")
.field("header", &self.header)
@@ -315,14 +342,14 @@ impl<'d> core::fmt::Debug for Item<'d> {
}

/// A version of [Item] that does not borrow the data. This is to circumvent the borrowchecker in some places.
pub struct ItemUnborrowed {
pub header: ItemHeader,
pub struct ItemUnborrowed<S> {
pub header: ItemHeader<S>,
data_buffer_len: usize,
}

impl ItemUnborrowed {
impl<S> ItemUnborrowed<S> {
/// Reborrows the data. Watch out! Make sure the data buffer hasn't changed since unborrowing!
pub fn reborrow(self, data_buffer: &mut [u8]) -> Item<'_> {
pub fn reborrow(self, data_buffer: &mut [u8]) -> Item<'_, S> {
Item {
header: self.header,
data_buffer: &mut data_buffer[..self.data_buffer_len],
@@ -359,7 +386,7 @@ pub async fn find_next_free_item_spot<S: NorFlash>(
}
};

if let Some(available) = ItemHeader::available_data_bytes::<S>(end_address - free_item_address)
if let Some(available) = ItemHeader::<S>::available_data_bytes(end_address - free_item_address)
{
if available >= data_length {
Ok(Some(free_item_address))
@@ -371,13 +398,13 @@ pub async fn find_next_free_item_spot<S: NorFlash>(
}
}

pub enum MaybeItem<'d> {
Corrupted(ItemHeader, &'d mut [u8]),
Erased(ItemHeader, &'d mut [u8]),
Present(Item<'d>),
pub enum MaybeItem<'d, S> {
Corrupted(ItemHeader<S>, &'d mut [u8]),
Erased(ItemHeader<S>, &'d mut [u8]),
Present(Item<'d, S>),
}

impl<'d> core::fmt::Debug for MaybeItem<'d> {
impl<'d, S: core::fmt::Debug> core::fmt::Debug for MaybeItem<'d, S> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Corrupted(arg0, arg1) => f
@@ -391,8 +418,8 @@ impl<'d> core::fmt::Debug for MaybeItem<'d> {
}
}

impl<'d> MaybeItem<'d> {
pub fn unwrap<E>(self) -> Result<Item<'d>, Error<E>> {
impl<'d, S> MaybeItem<'d, S> {
pub fn unwrap<E>(self) -> Result<Item<'d, S>, Error<E>> {
match self {
MaybeItem::Corrupted(_, _) => Err(Error::Corrupted {
#[cfg(feature = "_test")]
@@ -521,7 +548,7 @@ impl ItemIter {
&mut self,
flash: &mut S,
data_buffer: &'m mut [u8],
) -> Result<Option<(Item<'m>, u32)>, Error<S::Error>> {
) -> Result<Option<(Item<'m, S>, u32)>, Error<S::Error>> {
let mut data_buffer = Some(data_buffer);
while let (Some(header), address) = self.header.next(flash).await? {
let buffer = data_buffer.take().unwrap();
@@ -558,7 +585,7 @@ impl ItemHeaderIter {
pub async fn next<S: NorFlash>(
&mut self,
flash: &mut S,
) -> Result<(Option<ItemHeader>, u32), Error<S::Error>> {
) -> Result<(Option<ItemHeader<S>>, u32), Error<S::Error>> {
self.traverse(flash, |_, _| false).await
}

@@ -569,12 +596,12 @@ impl ItemHeaderIter {
pub async fn traverse<S: NorFlash>(
&mut self,
flash: &mut S,
callback: impl Fn(&ItemHeader, u32) -> bool,
) -> Result<(Option<ItemHeader>, u32), Error<S::Error>> {
callback: impl Fn(&ItemHeader<S>, u32) -> bool,
) -> Result<(Option<ItemHeader<S>>, 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);
let next_address = header.next_item_address(self.current_address);
if callback(&header, self.current_address) {
self.current_address = next_address;
} else {
@@ -587,7 +614,7 @@ impl ItemHeaderIter {
return Ok((None, self.current_address));
}
Err(Error::Corrupted { .. }) => {
self.current_address = ItemHeader::data_address::<S>(self.current_address);
self.current_address = ItemHeader::<S>::data_address(self.current_address);
}
Err(e) => return Err(e),
}
10 changes: 8 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ use core::{
fmt::Debug,
ops::{Deref, DerefMut, Range},
};
use embedded_storage_async::nor_flash::NorFlash;
use embedded_storage_async::nor_flash::{MultiwriteNorFlash, NorFlash};
use map::SerializationError;

#[cfg(feature = "arrayvec")]
@@ -32,6 +32,12 @@ pub mod mock_flash;
/// Many flashes have 4-byte or 1-byte words.
const MAX_WORD_SIZE: usize = 32;

// TODO: Move this to `embedded-storage`.
/// Marker trait that guarantees that a word can be cleared to all 0s.
pub trait WordclearNorFlash: NorFlash {}

impl<T> WordclearNorFlash for T where T: MultiwriteNorFlash {}

/// Resets the flash in the entire given flash range.
///
/// This is just a thin helper function as it just calls the flash's erase function.
@@ -54,7 +60,7 @@ pub async fn erase_all<S: NorFlash>(
/// The associated data of each item is additionally padded to a full flash word size, but that's not part of this number.
/// This means the full item length is `returned number + (data length).next_multiple_of(S::WORD_SIZE)`.
pub const fn item_overhead_size<S: NorFlash>() -> u32 {
item::ItemHeader::data_address::<S>(0)
item::ItemHeader::<S>::data_address(0)
}

// Type representing buffer aligned to 4 byte boundary.
8 changes: 3 additions & 5 deletions src/map.rs
Original file line number Diff line number Diff line change
@@ -161,7 +161,7 @@ async fn fetch_item_with_location<'d, K: Key, S: NorFlash>(
cache: &mut impl PrivateKeyCacheImpl<K>,
data_buffer: &'d mut [u8],
search_key: &K,
) -> Result<Option<(ItemUnborrowed, u32, Option<usize>)>, Error<S::Error>> {
) -> Result<Option<(ItemUnborrowed<S>, u32, Option<usize>)>, Error<S::Error>> {
assert_eq!(flash_range.start % S::ERASE_SIZE as u32, 0);
assert_eq!(flash_range.end % S::ERASE_SIZE as u32, 0);
assert!(flash_range.end - flash_range.start >= S::ERASE_SIZE as u32 * 2);
@@ -415,7 +415,7 @@ async fn store_item_inner<'d, K: Key, S: NorFlash>(
if item_data_length > u16::MAX as usize
|| item_data_length
> calculate_page_size::<S>()
.saturating_sub(ItemHeader::data_address::<S>(0) as usize)
.saturating_sub(ItemHeader::<S>::data_address(0) as usize)
{
cache.unmark_dirty();
return Err(Error::ItemTooBig);
@@ -908,9 +908,7 @@ async fn migrate_items<K: Key, S: NorFlash>(
found_item
.write(flash, flash_range.clone(), cache, next_page_write_address)
.await?;
next_page_write_address = found_item
.header
.next_item_address::<S>(next_page_write_address);
next_page_write_address = found_item.header.next_item_address(next_page_write_address);
}
}

4 changes: 2 additions & 2 deletions src/mock_flash.rs
Original file line number Diff line number Diff line change
@@ -154,7 +154,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) = it.traverse(self, |_, _| false).await.unwrap()
{
let next_item_address = header.next_item_address::<Self>(item_address);
let next_item_address = header.next_item_address(item_address);
let maybe_item = header
.read_item(self, &mut buf, item_address, page_data_end)
.await
@@ -198,7 +198,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) = it.traverse(self, |_, _| false).await.unwrap() {
let next_item_address = header.next_item_address::<Self>(item_address);
let next_item_address = header.next_item_address(item_address);

if (item_address..next_item_address).contains(&target_item_address) {
let maybe_item = header
18 changes: 9 additions & 9 deletions src/queue.rs
Original file line number Diff line number Diff line change
@@ -110,7 +110,7 @@ async fn push_inner<S: NorFlash>(
// Data must fit in a single page
if data.len() > u16::MAX as usize
|| data.len()
> calculate_page_size::<S>().saturating_sub(ItemHeader::data_address::<S>(0) as usize)
> calculate_page_size::<S>().saturating_sub(ItemHeader::<S>::data_address(0) as usize)
{
cache.unmark_dirty();
return Err(Error::ItemTooBig);
@@ -353,7 +353,7 @@ impl<'s, S: NorFlash, CI: CacheImpl> QueueIterator<'s, S, CI> {
async fn next_inner(
&mut self,
data_buffer: &mut [u8],
) -> Result<Option<(ItemUnborrowed, u32)>, Error<S::Error>> {
) -> Result<Option<(ItemUnborrowed<S>, u32)>, Error<S::Error>> {
let mut data_buffer = Some(data_buffer);

if self.cache.is_dirty() {
@@ -421,7 +421,7 @@ impl<'s, S: NorFlash, CI: CacheImpl> QueueIterator<'s, S, CI> {

match maybe_item {
item::MaybeItem::Corrupted(header, db) => {
let next_address = header.next_item_address::<S>(found_item_address);
let next_address = header.next_item_address(found_item_address);
self.next_address = if next_address >= page_data_end_address {
NextAddress::PageAfter(current_page)
} else {
@@ -431,7 +431,7 @@ impl<'s, S: NorFlash, CI: CacheImpl> QueueIterator<'s, S, CI> {
}
item::MaybeItem::Erased(_, _) => unreachable!("Item is already erased"),
item::MaybeItem::Present(item) => {
let next_address = item.header.next_item_address::<S>(found_item_address);
let next_address = item.header.next_item_address(found_item_address);
self.next_address = if next_address >= page_data_end_address {
NextAddress::PageAfter(current_page)
} else {
@@ -453,7 +453,7 @@ impl<'s, S: NorFlash, CI: CacheImpl> QueueIterator<'s, S, CI> {
pub struct QueueIteratorEntry<'s, 'd, 'q, S: NorFlash, CI: CacheImpl> {
iter: &'q mut QueueIterator<'s, S, CI>,
address: u32,
item: Item<'d>,
item: Item<'d, S>,
}

impl<'s, 'd, 'q, S: NorFlash, CI: CacheImpl> Deref for QueueIteratorEntry<'s, 'd, 'q, S, CI> {
@@ -579,7 +579,7 @@ async fn find_max_fit_inner<S: NorFlash>(
};

cache.unmark_dirty();
Ok(ItemHeader::available_data_bytes::<S>(
Ok(ItemHeader::<S>::available_data_bytes(
page_data_end_address - next_item_address,
))
}
@@ -657,7 +657,7 @@ async fn space_left_inner<S: NorFlash>(
}
};

if ItemHeader::available_data_bytes::<S>(page_data_end_address - next_item_address)
if ItemHeader::<S>::available_data_bytes(page_data_end_address - next_item_address)
.is_none()
{
// No data fits on this partial open page anymore.
@@ -1237,7 +1237,7 @@ mod tests {
avg_reads: 8.0188,
avg_writes: 1.0,
avg_bytes_read: 96.4224,
avg_bytes_written: 8.0
avg_bytes_written: 4.0
}
);
}
@@ -1347,7 +1347,7 @@ mod tests {
avg_reads: 82.618,
avg_writes: 1.0,
avg_bytes_read: 567.9904,
avg_bytes_written: 8.0
avg_bytes_written: 4.0
}
);
}

0 comments on commit 798be4f

Please sign in to comment.