QueueStorage

Struct QueueStorage 

Source
pub struct QueueStorage<S: NorFlash, C: CacheImpl> { /* private fields */ }
Expand description

A fifo queue storage

Use Self::push to add data to the fifo and use Self::peek and Self::pop to get the data back.

§Basic API


// Initialize the flash. This can be internal or external
let mut flash = init_flash();

let mut storage = QueueStorage::new(flash, const { QueueConfig::new(0x1000..0x3000) }, NoCache::new());
// We need to give the crate a buffer to work with.
// It must be big enough to serialize the biggest value of your storage type in.
let mut data_buffer = [0; 128];

let my_data = [10, 47, 29];

// We can push some data to the queue
storage.push(&my_data, false).await.unwrap();

// We can peek at the oldest data

assert_eq!(
    &storage.peek(&mut data_buffer).await.unwrap().unwrap()[..],
    &my_data[..]
);

// With popping we get back the oldest data, but that data is now also removed

assert_eq!(
    &storage.pop(&mut data_buffer).await.unwrap().unwrap()[..],
    &my_data[..]
);

// If we pop again, we find there's no data anymore

assert_eq!(
    storage.pop(&mut data_buffer).await,
    Ok(None)
);

Implementations§

Source§

impl<S: NorFlash, C: CacheImpl> QueueStorage<S, C>

Source

pub const fn new(storage: S, config: QueueConfig<S>, cache: C) -> Self

Create a new (fifo) queue instance

The provided cache instance must be new or must be in the exact correct state for the current flash contents. If the cache is bad, undesirable things will happen. So, it’s ok to reuse the cache gotten from the Self::destroy method when the flash hasn’t changed since calling destroy.

Source

pub async fn push( &mut self, data: &[u8], allow_overwrite_old_data: bool, ) -> Result<(), Error<S::Error>>

Push data into the queue. The data can only be taken out with the Self::pop function.

Old data will not be overwritten unless allow_overwrite_old_data is true. If it is, then if the queue is full, the oldest data is removed to make space for the new data.

Note: If a page is already used and you push more data than the remaining capacity of the page, the entire remaining capacity will go unused because the data is stored on the next page.

Source

pub async fn iter(&mut self) -> Result<QueueIterator<'_, S, C>, Error<S::Error>>

Get an iterator-like interface to iterate over the items stored in the queue. This goes from oldest to newest.

The iteration happens non-destructively, or in other words it peeks at every item. The returned entry has a QueueIteratorEntry::pop function with which you can decide to pop the item after you’ve seen the contents.

Source

pub async fn peek<'d>( &mut self, data_buffer: &'d mut [u8], ) -> Result<Option<&'d mut [u8]>, Error<S::Error>>

Peek at the oldest data.

If you also want to remove the data use Self::pop.

The data is written to the given data_buffer and the part that was written is returned. It is valid to only use the length of the returned slice and use the original data_buffer. The data_buffer may contain extra data on ranges after the returned slice. You should not depend on that data.

If the data buffer is not big enough an error is returned.

Source

pub async fn pop<'d>( &mut self, data_buffer: &'d mut [u8], ) -> Result<Option<&'d mut [u8]>, Error<S::Error>>

Pop the oldest data from the queue.

If you don’t want to remove the data use Self::peek.

The data is written to the given data_buffer and the part that was written is returned. It is valid to only use the length of the returned slice and use the original data_buffer. The data_buffer may contain extra data on ranges after the returned slice. You should not depend on that data.

If the data buffer is not big enough an error is returned.

Source

pub async fn find_max_fit(&mut self) -> Result<Option<u32>, Error<S::Error>>

Find the largest size of data that can be stored.

This will read through the entire flash to find the largest chunk of data that can be stored, taking alignment requirements of the item into account.

If there is no space left, None is returned.

Source

pub async fn space_left(&mut self) -> Result<u32, Error<S::Error>>

Calculate how much space is left free in the queue (in bytes).

The number given back is accurate, however there are lots of things that add overhead and padding. Every push is an item with its own overhead. You can check the overhead per item with Self::item_overhead_size.

Furthermore, every item has to fully fit in a page. So if a page has 50 bytes left and you push an item of 60 bytes, the current page is closed and the item is stored on the next page, ‘wasting’ the 50 you had.

So unless you’re tracking all this, the returned number should only be used as a rough indication.

Source

pub fn erase_all(&mut self) -> impl Future<Output = Result<(), Error<S::Error>>>

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.

Source

pub const fn item_overhead_size() -> u32

Get the minimal overhead size per stored item for the given flash type.

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).

Source

pub fn destroy(self) -> (S, C)

Destroy the instance to get back the flash and the cache.

The cache can be passed to a new storage instance, but only for the same flash region and if nothing has changed in flash.

Source

pub const fn flash(&mut self) -> &mut S

Get a reference to the flash. Mutating the memory is at your own risk.

Source

pub const fn flash_range(&self) -> Range<u32>

Get the flash range being used

Auto Trait Implementations§

§

impl<S, C> Freeze for QueueStorage<S, C>
where S: Freeze, C: Freeze,

§

impl<S, C> RefUnwindSafe for QueueStorage<S, C>

§

impl<S, C> Send for QueueStorage<S, C>
where S: Send, C: Send,

§

impl<S, C> Sync for QueueStorage<S, C>
where S: Sync, C: Sync,

§

impl<S, C> Unpin for QueueStorage<S, C>
where S: Unpin, C: Unpin,

§

impl<S, C> UnwindSafe for QueueStorage<S, C>
where S: UnwindSafe, C: UnwindSafe,

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.