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 implementingFlashSLOT_SIZE- The size of each slot in bytes: this must match your flash’s underlying sector/page sizeSLOT_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>
impl<F: Flash, const SLOT_SIZE: usize, const SLOT_COUNT: usize> Storage<F, SLOT_SIZE, SLOT_COUNT>
Sourcepub const SPACE: u32
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.
Sourcepub const fn new(flash: F) -> Self
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.
Sourcepub fn scan(&mut self) -> Result<Option<Slot>, F::Error>
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.
Sourcepub fn erase(&mut self, idx: usize) -> Result<(), F::Error>
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.
Sourcepub fn erase_all(&mut self) -> Result<(), F::Error>
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.
Sourcepub fn read<'a>(
&mut self,
idx: usize,
buf: &'a mut [u8],
) -> Result<Option<&'a mut [u8]>, F::Error>
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.
Sourcepub fn read_static<const SIZE: usize>(
&mut self,
idx: usize,
buf: &mut [u8; SIZE],
) -> Result<(), F::Error>
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.
Sourcepub fn write(
&mut self,
idx: usize,
prev: Chksum,
data: &mut [u8],
) -> Result<(usize, Chksum), F::Error>
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.
Sourcepub fn write_static<const SIZE: usize>(
&mut self,
idx: usize,
prev: Chksum,
data: &mut [u8; SIZE],
) -> Result<(usize, Chksum), F::Error>
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.
Sourcepub fn append(&mut self, data: &mut [u8]) -> Result<(), F::Error>
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.
Sourcepub fn append_static<const SIZE: usize>(
&mut self,
data: &mut [u8; SIZE],
) -> Result<(), F::Error>
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.
Sourcepub const fn reset(&mut self)
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.
Sourcepub fn into_inner(self) -> F
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.