use alloc::borrow::Cow;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct StorageIndex {
pub page: usize,
pub byte: usize,
}
#[derive(Debug, PartialEq, Eq)]
pub enum StorageError {
NotAligned,
OutOfBounds,
CustomError,
}
#[cfg(feature = "std")]
impl From<std::io::Error> for StorageError {
fn from(_: std::io::Error) -> Self {
Self::CustomError
}
}
pub type StorageResult<T> = Result<T, StorageError>;
pub trait Storage {
fn word_size(&self) -> usize;
fn page_size(&self) -> usize;
fn num_pages(&self) -> usize;
fn max_word_writes(&self) -> usize;
fn max_page_erases(&self) -> usize;
fn read_slice(&self, index: StorageIndex, length: usize) -> StorageResult<Cow<[u8]>>;
fn write_slice(&mut self, index: StorageIndex, value: &[u8]) -> StorageResult<()>;
fn erase_page(&mut self, page: usize) -> StorageResult<()>;
}
impl StorageIndex {
fn is_valid(self, length: usize, storage: &impl Storage) -> bool {
let page_size = storage.page_size();
self.page < storage.num_pages() && length <= page_size && self.byte <= page_size - length
}
pub fn range(
self, length: usize, storage: &impl Storage,
) -> StorageResult<core::ops::Range<usize>> {
if self.is_valid(length, storage) {
let start = self.page * storage.page_size() + self.byte;
Ok(start .. start + length)
} else {
Err(StorageError::OutOfBounds)
}
}
}