Allow read_slice to return a Vec
This commit is contained in:
@@ -194,10 +194,10 @@ fn main() {
|
|||||||
write_matrix(matrix);
|
write_matrix(matrix);
|
||||||
|
|
||||||
// Results for nrf52840dk_opensk:
|
// Results for nrf52840dk_opensk:
|
||||||
// StorageConfig { page_size: 4096, num_pages: 20 }
|
// StorageConfig { num_pages: 20 }
|
||||||
// Overwrite Length Boot Compaction Insert Remove
|
// Overwrite Length Boot Compaction Insert Remove
|
||||||
// no 50 words 16.2 ms 143.8 ms 18.3 ms 8.4 ms
|
// no 50 words 18.6 ms 145.8 ms 21.0 ms 9.8 ms
|
||||||
// yes 1 words 303.8 ms 97.9 ms 9.7 ms 4.7 ms
|
// yes 1 words 335.8 ms 100.6 ms 11.7 ms 5.7 ms
|
||||||
}
|
}
|
||||||
|
|
||||||
fn align(x: &str, n: usize) {
|
fn align(x: &str, n: usize) {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
//! actual flash storage. Instead it uses a buffer in memory to represent the storage state.
|
//! actual flash storage. Instead it uses a buffer in memory to represent the storage state.
|
||||||
|
|
||||||
use crate::{Storage, StorageError, StorageIndex, StorageResult};
|
use crate::{Storage, StorageError, StorageIndex, StorageResult};
|
||||||
use alloc::borrow::Borrow;
|
use alloc::borrow::{Borrow, Cow};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
|
|
||||||
@@ -301,8 +301,8 @@ impl Storage for BufferStorage {
|
|||||||
self.options.max_page_erases
|
self.options.max_page_erases
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_slice(&self, index: StorageIndex, length: usize) -> StorageResult<&[u8]> {
|
fn read_slice(&self, index: StorageIndex, length: usize) -> StorageResult<Cow<[u8]>> {
|
||||||
Ok(&self.storage[index.range(length, self)?])
|
Ok(Cow::Borrowed(&self.storage[index.range(length, self)?]))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_slice(&mut self, index: StorageIndex, value: &[u8]) -> StorageResult<()> {
|
fn write_slice(&mut self, index: StorageIndex, value: &[u8]) -> StorageResult<()> {
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
//! Flash storage abstraction.
|
//! Flash storage abstraction.
|
||||||
|
|
||||||
|
use alloc::borrow::Cow;
|
||||||
|
|
||||||
/// Represents a byte position in a storage.
|
/// Represents a byte position in a storage.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct StorageIndex {
|
pub struct StorageIndex {
|
||||||
@@ -60,7 +62,7 @@ pub trait Storage {
|
|||||||
/// Reads a byte slice from the storage.
|
/// Reads a byte slice from the storage.
|
||||||
///
|
///
|
||||||
/// The `index` must designate `length` bytes in the storage.
|
/// The `index` must designate `length` bytes in the storage.
|
||||||
fn read_slice(&self, index: StorageIndex, length: usize) -> StorageResult<&[u8]>;
|
fn read_slice(&self, index: StorageIndex, length: usize) -> StorageResult<Cow<[u8]>>;
|
||||||
|
|
||||||
/// Writes a word slice to the storage.
|
/// Writes a word slice to the storage.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ use crate::{usize_to_nat, Nat, Storage, StorageError, StorageIndex};
|
|||||||
pub use crate::{
|
pub use crate::{
|
||||||
BufferStorage, StoreDriver, StoreDriverOff, StoreDriverOn, StoreInterruption, StoreInvariant,
|
BufferStorage, StoreDriver, StoreDriverOff, StoreDriverOn, StoreInterruption, StoreInvariant,
|
||||||
};
|
};
|
||||||
|
use alloc::borrow::Cow;
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::borrow::Borrow;
|
use core::borrow::Borrow;
|
||||||
@@ -490,7 +491,8 @@ impl<S: Storage> Store<S> {
|
|||||||
fn recover_initialize(&mut self) -> StoreResult<()> {
|
fn recover_initialize(&mut self) -> StoreResult<()> {
|
||||||
let word_size = self.format.word_size();
|
let word_size = self.format.word_size();
|
||||||
for page in 0..self.format.num_pages() {
|
for page in 0..self.format.num_pages() {
|
||||||
let (init, rest) = self.read_page(page).split_at(word_size as usize);
|
let content = self.read_page(page);
|
||||||
|
let (init, rest) = content.split_at(word_size as usize);
|
||||||
if (page > 0 && !is_erased(init)) || !is_erased(rest) {
|
if (page > 0 && !is_erased(init)) || !is_erased(rest) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -890,7 +892,7 @@ impl<S: Storage> Store<S> {
|
|||||||
|
|
||||||
/// Sets the padding bit of a user header.
|
/// Sets the padding bit of a user header.
|
||||||
fn set_padding(&mut self, pos: Position) -> StoreResult<()> {
|
fn set_padding(&mut self, pos: Position) -> StoreResult<()> {
|
||||||
let mut word = Word::from_slice(self.read_word(pos));
|
let mut word = Word::from_slice(&self.read_word(pos));
|
||||||
self.format.set_padding(&mut word)?;
|
self.format.set_padding(&mut word)?;
|
||||||
self.write_slice(pos, &word.as_slice())?;
|
self.write_slice(pos, &word.as_slice())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -898,7 +900,7 @@ impl<S: Storage> Store<S> {
|
|||||||
|
|
||||||
/// Sets the deleted bit of a user header.
|
/// Sets the deleted bit of a user header.
|
||||||
fn set_deleted(&mut self, pos: Position) -> StoreResult<()> {
|
fn set_deleted(&mut self, pos: Position) -> StoreResult<()> {
|
||||||
let mut word = Word::from_slice(self.read_word(pos));
|
let mut word = Word::from_slice(&self.read_word(pos));
|
||||||
self.format.set_deleted(&mut word);
|
self.format.set_deleted(&mut word);
|
||||||
self.write_slice(pos, &word.as_slice())?;
|
self.write_slice(pos, &word.as_slice())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -1001,13 +1003,13 @@ impl<S: Storage> Store<S> {
|
|||||||
0 => None,
|
0 => None,
|
||||||
_ => Some(self.read_word(*pos + length)),
|
_ => Some(self.read_word(*pos + length)),
|
||||||
};
|
};
|
||||||
if header.check(footer) {
|
if header.check(footer.as_deref()) {
|
||||||
if header.key > self.format.max_key() {
|
if header.key > self.format.max_key() {
|
||||||
return Err(StoreError::InvalidStorage);
|
return Err(StoreError::InvalidStorage);
|
||||||
}
|
}
|
||||||
*pos += 1 + length;
|
*pos += 1 + length;
|
||||||
ParsedEntry::User(header)
|
ParsedEntry::User(header)
|
||||||
} else if footer.map_or(true, |x| is_erased(x)) {
|
} else if footer.map_or(true, |x| is_erased(&x)) {
|
||||||
self.parse_partial(pos)
|
self.parse_partial(pos)
|
||||||
} else {
|
} else {
|
||||||
*pos += 1 + length;
|
*pos += 1 + length;
|
||||||
@@ -1028,7 +1030,7 @@ impl<S: Storage> Store<S> {
|
|||||||
fn parse_partial(&self, pos: &mut Position) -> ParsedEntry {
|
fn parse_partial(&self, pos: &mut Position) -> ParsedEntry {
|
||||||
let mut length = None;
|
let mut length = None;
|
||||||
for i in 0..self.format.max_prefix_len() {
|
for i in 0..self.format.max_prefix_len() {
|
||||||
if !is_erased(self.read_word(*pos + i)) {
|
if !is_erased(&self.read_word(*pos + i)) {
|
||||||
length = Some(i);
|
length = Some(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1045,20 +1047,20 @@ impl<S: Storage> Store<S> {
|
|||||||
fn parse_init(&self, page: Nat) -> StoreResult<WordState<InitInfo>> {
|
fn parse_init(&self, page: Nat) -> StoreResult<WordState<InitInfo>> {
|
||||||
let index = self.format.index_init(page);
|
let index = self.format.index_init(page);
|
||||||
let word = self.storage_read_slice(index, self.format.word_size());
|
let word = self.storage_read_slice(index, self.format.word_size());
|
||||||
self.format.parse_init(Word::from_slice(word))
|
self.format.parse_init(Word::from_slice(&word))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the compact info of a page.
|
/// Parses the compact info of a page.
|
||||||
fn parse_compact(&self, page: Nat) -> StoreResult<WordState<CompactInfo>> {
|
fn parse_compact(&self, page: Nat) -> StoreResult<WordState<CompactInfo>> {
|
||||||
let index = self.format.index_compact(page);
|
let index = self.format.index_compact(page);
|
||||||
let word = self.storage_read_slice(index, self.format.word_size());
|
let word = self.storage_read_slice(index, self.format.word_size());
|
||||||
self.format.parse_compact(Word::from_slice(word))
|
self.format.parse_compact(Word::from_slice(&word))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a word from the virtual storage.
|
/// Parses a word from the virtual storage.
|
||||||
fn parse_word(&self, pos: Position) -> StoreResult<WordState<ParsedWord>> {
|
fn parse_word(&self, pos: Position) -> StoreResult<WordState<ParsedWord>> {
|
||||||
self.format
|
self.format
|
||||||
.parse_word(Word::from_slice(self.read_word(pos)))
|
.parse_word(Word::from_slice(&self.read_word(pos)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a slice from the virtual storage.
|
/// Reads a slice from the virtual storage.
|
||||||
@@ -1068,22 +1070,22 @@ impl<S: Storage> Store<S> {
|
|||||||
let mut result = Vec::with_capacity(length as usize);
|
let mut result = Vec::with_capacity(length as usize);
|
||||||
let index = pos.index(&self.format);
|
let index = pos.index(&self.format);
|
||||||
let max_length = self.format.page_size() - usize_to_nat(index.byte);
|
let max_length = self.format.page_size() - usize_to_nat(index.byte);
|
||||||
result.extend_from_slice(self.storage_read_slice(index, min(length, max_length)));
|
result.extend_from_slice(&self.storage_read_slice(index, min(length, max_length)));
|
||||||
if length > max_length {
|
if length > max_length {
|
||||||
// The slice spans the next page.
|
// The slice spans the next page.
|
||||||
let index = pos.next_page(&self.format).index(&self.format);
|
let index = pos.next_page(&self.format).index(&self.format);
|
||||||
result.extend_from_slice(self.storage_read_slice(index, length - max_length));
|
result.extend_from_slice(&self.storage_read_slice(index, length - max_length));
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a word from the virtual storage.
|
/// Reads a word from the virtual storage.
|
||||||
fn read_word(&self, pos: Position) -> &[u8] {
|
fn read_word(&self, pos: Position) -> Cow<[u8]> {
|
||||||
self.storage_read_slice(pos.index(&self.format), self.format.word_size())
|
self.storage_read_slice(pos.index(&self.format), self.format.word_size())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a physical page.
|
/// Reads a physical page.
|
||||||
fn read_page(&self, page: Nat) -> &[u8] {
|
fn read_page(&self, page: Nat) -> Cow<[u8]> {
|
||||||
let index = StorageIndex {
|
let index = StorageIndex {
|
||||||
page: page as usize,
|
page: page as usize,
|
||||||
byte: 0,
|
byte: 0,
|
||||||
@@ -1092,7 +1094,7 @@ impl<S: Storage> Store<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a slice from the physical storage.
|
/// Reads a slice from the physical storage.
|
||||||
fn storage_read_slice(&self, index: StorageIndex, length: Nat) -> &[u8] {
|
fn storage_read_slice(&self, index: StorageIndex, length: Nat) -> Cow<[u8]> {
|
||||||
// The only possible failures are if the slice spans multiple pages.
|
// The only possible failures are if the slice spans multiple pages.
|
||||||
self.storage.read_slice(index, length as usize).unwrap()
|
self.storage.read_slice(index, length as usize).unwrap()
|
||||||
}
|
}
|
||||||
@@ -1142,7 +1144,7 @@ impl<S: Storage> Store<S> {
|
|||||||
|
|
||||||
/// Erases a page if not already erased.
|
/// Erases a page if not already erased.
|
||||||
fn storage_erase_page(&mut self, page: Nat) -> StoreResult<()> {
|
fn storage_erase_page(&mut self, page: Nat) -> StoreResult<()> {
|
||||||
if !is_erased(self.read_page(page)) {
|
if !is_erased(&self.read_page(page)) {
|
||||||
self.storage.erase_page(page as usize)?;
|
self.storage.erase_page(page as usize)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
5
src/env/tock/storage.rs
vendored
5
src/env/tock/storage.rs
vendored
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
use crate::api::upgrade_storage::helper::{find_slice, is_aligned, ModRange};
|
use crate::api::upgrade_storage::helper::{find_slice, is_aligned, ModRange};
|
||||||
use crate::api::upgrade_storage::UpgradeStorage;
|
use crate::api::upgrade_storage::UpgradeStorage;
|
||||||
|
use alloc::borrow::Cow;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use libtock_core::{callback, syscalls};
|
use libtock_core::{callback, syscalls};
|
||||||
@@ -196,9 +197,9 @@ impl Storage for TockStorage {
|
|||||||
self.max_page_erases
|
self.max_page_erases
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_slice(&self, index: StorageIndex, length: usize) -> StorageResult<&[u8]> {
|
fn read_slice(&self, index: StorageIndex, length: usize) -> StorageResult<Cow<[u8]>> {
|
||||||
let start = index.range(length, self)?.start;
|
let start = index.range(length, self)?.start;
|
||||||
find_slice(&self.storage_locations, start, length)
|
find_slice(&self.storage_locations, start, length).map(Cow::Borrowed)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_slice(&mut self, index: StorageIndex, value: &[u8]) -> StorageResult<()> {
|
fn write_slice(&mut self, index: StorageIndex, value: &[u8]) -> StorageResult<()> {
|
||||||
|
|||||||
Reference in New Issue
Block a user