Storage

Struct Storage 

Source
pub struct Storage<F: Flash, const SLOT_SIZE: usize, const SLOT_COUNT: usize> { /* private fields */ }
Expand description

Savegame storage manager

Manages reading and writing savegames to flash memory with power-fail safety and wear leveling. The storage area is divided into fixed-size slots, and savegames are written sequentially across slots with automatic wrap-around.

§Type Parameters

  • F - The flash hardware type implementing Flash
  • SLOT_SIZE - The size of each slot in bytes: this must match your flash’s underlying sector/page size
  • SLOT_COUNT - The total number of slots available

§Power-fail Safety

Writes are atomic at the slot level. The slot header is written last, so a power failure during write leaves the previous savegame intact. The scanner follows the checksum chain to find the most recent complete savegame.

§Wear Leveling

Savegames are written sequentially with wrap-around, distributing writes evenly across all slots to maximize flash memory lifespan.

Implementations§

Source§

impl<F: Flash, const SLOT_SIZE: usize, const SLOT_COUNT: usize> Storage<F, SLOT_SIZE, SLOT_COUNT>

Source

pub const SPACE: u32

The total size of the storage area in bytes

This can’t be fully used for data storage, as some bytes are used for slot metadata and headers.

Source

pub const fn new(flash: F) -> Self

Create a new storage manager

This is a cheap operation and does not initialize or scan the flash memory.

Source

pub fn scan(&mut self) -> Result<Option<Slot>, F::Error>

Scan all slots for the most recent valid savegame

If found, updates internal state to point to the next free slot. If no valid savegame is found, internal state is unchanged and Ok(None) is returned.

Source

pub fn erase(&mut self, idx: usize) -> Result<(), F::Error>

Mark a slot as unused (by partially or fully erasing it)

This may not securely erase all data (depending on the flash chip), but prevents the slot from being detected as a valid savegame.

Source

pub fn erase_all(&mut self) -> Result<(), F::Error>

Mark all slots as unused

This may not securely erase data (depending on the flash chip), but prevents them from being detected as valid savegames.

On some flash chips, this may be optimized to a bulk erase operation.

Source

pub fn read<'a>( &mut self, idx: usize, buf: &'a mut [u8], ) -> Result<Option<&'a mut [u8]>, F::Error>

Read a savegame from a specific slot index

The slot index must point to the first slot of the savegame. This method reads the header to determine the savegame length. If the buffer is not large enough to hold the entire savegame, Ok(None) is returned. The savegame may span multiple slots.

Source

pub fn read_static<const SIZE: usize>( &mut self, idx: usize, buf: &mut [u8; SIZE], ) -> Result<(), F::Error>

Read a static-sized savegame directly from a single slot

This is a more lightweight read operation for fixed-size data that fits within a single slot (excluding the header). The size must not exceed SLOT_SIZE - Slot::HEADER_SIZE. The embedded length field is ignored.

Source

pub fn write( &mut self, idx: usize, prev: Chksum, data: &mut [u8], ) -> Result<(usize, Chksum), F::Error>

Write a savegame starting at a specific slot index

If the data doesn’t fit in a single slot, this method automatically continues to subsequent slots, erasing them as needed. Returns the next free slot index and the checksum of the savegame that was just written.

Source

pub fn write_static<const SIZE: usize>( &mut self, idx: usize, prev: Chksum, data: &mut [u8; SIZE], ) -> Result<(usize, Chksum), F::Error>

Write a static-sized savegame directly into a single slot

This is a more lightweight write operation for fixed-size data that fits within a single slot (excluding the header). The size must not exceed SLOT_SIZE - Slot::HEADER_SIZE.

Source

pub fn append(&mut self, data: &mut [u8]) -> Result<(), F::Error>

Append a new savegame at the next free slot

The new savegame indicates it’s an update to the previous savegame, when fully written the scanner should find it as the most recent savegame.

Source

pub fn append_static<const SIZE: usize>( &mut self, data: &mut [u8; SIZE], ) -> Result<(), F::Error>

Append a static-sized savegame into the next free slot

This is a more lightweight write operation for fixed-size data that fits within a single slot (excluding the header). The size must not exceed SLOT_SIZE - Slot::HEADER_SIZE.

Source

pub const fn reset(&mut self)

Reset internal state to initial values

This does not erase any data, but causes the next write to start at slot 0 with a zeroed previous checksum.

Source

pub fn into_inner(self) -> F

Consume the storage manager and return the underlying flash device

This can be used to retrieve the flash device after all storage operations are complete.

Trait Implementations§

Source§

impl<F: Debug + Flash, const SLOT_SIZE: usize, const SLOT_COUNT: usize> Debug for Storage<F, SLOT_SIZE, SLOT_COUNT>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<F, const SLOT_SIZE: usize, const SLOT_COUNT: usize> Freeze for Storage<F, SLOT_SIZE, SLOT_COUNT>
where F: Freeze,

§

impl<F, const SLOT_SIZE: usize, const SLOT_COUNT: usize> RefUnwindSafe for Storage<F, SLOT_SIZE, SLOT_COUNT>
where F: RefUnwindSafe,

§

impl<F, const SLOT_SIZE: usize, const SLOT_COUNT: usize> Send for Storage<F, SLOT_SIZE, SLOT_COUNT>
where F: Send,

§

impl<F, const SLOT_SIZE: usize, const SLOT_COUNT: usize> Sync for Storage<F, SLOT_SIZE, SLOT_COUNT>
where F: Sync,

§

impl<F, const SLOT_SIZE: usize, const SLOT_COUNT: usize> Unpin for Storage<F, SLOT_SIZE, SLOT_COUNT>
where F: Unpin,

§

impl<F, const SLOT_SIZE: usize, const SLOT_COUNT: usize> UnwindSafe for Storage<F, SLOT_SIZE, SLOT_COUNT>
where F: UnwindSafe,

Blanket Implementations§

Source§

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

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

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

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

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

Source§

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

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

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

Source§

fn into(self) -> U

Calls U::from(self).

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

Source§

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

Source§

type Error = Infallible

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

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

Performs the conversion.
Source§

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

Source§

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

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

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

Performs the conversion.