Skip to main content

wasefire_store/
store.rs

1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Store implementation.
16
17use alloc::borrow::Cow;
18use alloc::boxed::Box;
19use alloc::vec::Vec;
20use core::borrow::Borrow;
21use core::cmp::{Ordering, max, min};
22use core::convert::TryFrom;
23#[cfg(feature = "std")]
24use std::collections::HashSet;
25
26use wasefire_error::{Code, Error, Space};
27
28use crate::format::{
29    CompactInfo, Format, Header, InitInfo, InternalEntry, Padding, ParsedWord, Position, Word,
30    WordState, is_erased,
31};
32#[cfg(feature = "std")]
33use crate::{BufferStorage, StoreOperation};
34use crate::{Nat, Storage, StorageIndex, usize_to_nat};
35
36/// Invalid argument.
37///
38/// The store is left unchanged. The operation will repeatedly fail until the argument is fixed.
39pub const INVALID_ARGUMENT: Error =
40    Error::new_const(Space::User as u8, Code::InvalidArgument as u16);
41
42/// Not enough capacity.
43///
44/// The store is left unchanged. The operation will repeatedly fail until capacity is freed.
45pub const NO_CAPACITY: Error = Error::new_const(Space::World as u8, Code::NotEnough as u16);
46
47/// Reached end of lifetime.
48///
49/// The store is left unchanged. The operation will repeatedly fail until emergency lifetime is
50/// added.
51pub const NO_LIFETIME: Error = Error::new_const(Space::World as u8, Code::OutOfBounds as u16);
52
53/// Storage is invalid.
54///
55/// The storage should be erased and the store [recovered](Store::recover). The store would be empty
56/// and have lost track of lifetime.
57pub const INVALID_STORAGE: Error = Error::new_const(Space::World as u8, Code::InvalidState as u16);
58
59/// Progression ratio for store metrics.
60///
61/// This is used for the [`Store::capacity`] and [`Store::lifetime`] metrics. Those metrics are
62/// measured in words.
63///
64/// # Invariant
65///
66/// - The used value does not exceed the total: `used` <= `total`.
67#[derive(Copy, Clone, Debug, PartialEq, Eq)]
68pub struct StoreRatio {
69    /// How much of the metric is used.
70    pub(crate) used: Nat,
71
72    /// How much of the metric can be used at most.
73    pub(crate) total: Nat,
74}
75
76impl StoreRatio {
77    /// How much of the metric is used.
78    pub fn used(self) -> usize {
79        self.used as usize
80    }
81
82    /// How much of the metric can be used at most.
83    pub fn total(self) -> usize {
84        self.total as usize
85    }
86
87    /// How much of the metric is remaining.
88    pub fn remaining(self) -> usize {
89        (self.total - self.used) as usize
90    }
91}
92
93/// Safe pointer to an entry.
94///
95/// A store handle stays valid at least until the next mutable operation. Store operations taking a
96/// handle as argument always verify that the handle is still valid.
97#[derive(Clone, Debug)]
98pub struct StoreHandle {
99    /// The key of the entry.
100    key: Nat,
101
102    /// The position of the entry.
103    pos: Position,
104
105    /// The length in bytes of the value.
106    len: Nat,
107}
108
109impl StoreHandle {
110    /// Returns the key of the entry.
111    pub fn get_key(&self) -> usize {
112        self.key as usize
113    }
114
115    /// Returns the value length of the entry.
116    ///
117    /// # Errors
118    ///
119    /// Returns [`INVALID_ARGUMENT`] if the entry has been deleted or compacted.
120    pub fn get_length<S: Storage>(&self, store: &Store<S>) -> Result<usize, Error> {
121        store.get_length(self)
122    }
123
124    /// Returns the value of the entry.
125    ///
126    /// # Errors
127    ///
128    /// Returns [`INVALID_ARGUMENT`] if the entry has been deleted or compacted.
129    pub fn get_value<S: Storage>(&self, store: &Store<S>) -> Result<Vec<u8>, Error> {
130        store.get_value(self)
131    }
132}
133
134/// Represents an update to the store as part of a transaction.
135#[derive(Clone, Debug)]
136pub enum StoreUpdate<ByteSlice: Borrow<[u8]>> {
137    /// Inserts or replaces an entry in the store.
138    Insert { key: usize, value: ByteSlice },
139
140    /// Removes an entry from the store.
141    Remove { key: usize },
142}
143
144impl<ByteSlice: Borrow<[u8]>> StoreUpdate<ByteSlice> {
145    /// Returns the key affected by the update.
146    pub fn key(&self) -> usize {
147        match *self {
148            StoreUpdate::Insert { key, .. } => key,
149            StoreUpdate::Remove { key } => key,
150        }
151    }
152
153    /// Returns the value written by the update.
154    pub fn value(&self) -> Option<&[u8]> {
155        match self {
156            StoreUpdate::Insert { value, .. } => Some(value.borrow()),
157            StoreUpdate::Remove { .. } => None,
158        }
159    }
160}
161
162pub type StoreIter<'a> = Box<dyn Iterator<Item = Result<StoreHandle, Error>> + 'a>;
163
164/// Implements a store with a map interface over a storage.
165#[derive(Clone)]
166pub struct Store<S: Storage> {
167    /// The underlying storage.
168    storage: S,
169
170    /// The storage configuration.
171    format: Format,
172
173    /// The position of the first word in the store.
174    head: Option<Position>,
175
176    /// The list of the position of the user entries.
177    ///
178    /// The position is encoded as the word offset from the [head](Store::head).
179    entries: Option<Vec<u16>>,
180}
181
182impl<S: Storage> Store<S> {
183    /// Resumes or initializes a store for a given storage.
184    ///
185    /// If the storage is completely erased, it is initialized. Otherwise, a possible interrupted
186    /// operation is recovered by being either completed or rolled-back. In case of error, the
187    /// storage ownership is returned.
188    ///
189    /// # Errors
190    ///
191    /// Returns [`INVALID_ARGUMENT`] if the storage is not
192    /// [supported](Format::is_storage_supported).
193    pub fn new(storage: S) -> Result<Store<S>, (Error, S)> {
194        let format = match Format::new(&storage) {
195            None => return Err((INVALID_ARGUMENT, storage)),
196            Some(x) => x,
197        };
198        let mut store = Store { storage, format, head: None, entries: None };
199        if let Err(error) = store.recover() {
200            return Err((error, store.storage));
201        }
202        Ok(store)
203    }
204
205    /// Extracts the storage.
206    pub fn extract_storage(self) -> S {
207        self.storage
208    }
209
210    /// Iterates over the entries.
211    pub fn iter(&self) -> Result<StoreIter<'_>, Error> {
212        let head = self.head.ok_or(INVALID_STORAGE)?;
213        Ok(Box::new(self.entries.as_ref().ok_or(INVALID_STORAGE)?.iter().map(move |&offset| {
214            let pos = head + offset as Nat;
215            match self.parse_entry(&mut pos.clone())? {
216                ParsedEntry::User(Header { key, length: len, .. }) => {
217                    Ok(StoreHandle { key, pos, len })
218                }
219                _ => Err(INVALID_STORAGE),
220            }
221        })))
222    }
223
224    /// Returns the current and total capacity in words.
225    ///
226    /// The capacity represents the size of what is stored.
227    pub fn capacity(&self) -> Result<StoreRatio, Error> {
228        let total = self.format.total_capacity();
229        let mut used = 0;
230        for handle in self.iter()? {
231            let handle = handle?;
232            used += 1 + self.format.bytes_to_words(handle.len);
233        }
234        Ok(StoreRatio { used, total })
235    }
236
237    /// Returns the current and total lifetime in words.
238    ///
239    /// The lifetime represents the age of the storage. The limit is an over-approximation by at
240    /// most the maximum length of a value (the actual limit depends on the length of the prefix of
241    /// the first physical page once all its erase cycles have been used).
242    pub fn lifetime(&self) -> Result<StoreRatio, Error> {
243        let total = self.format.total_lifetime().get();
244        let used = self.tail()?.get();
245        Ok(StoreRatio { used, total })
246    }
247
248    /// Applies a sequence of updates as a single transaction.
249    ///
250    /// # Errors
251    ///
252    /// Returns [`INVALID_ARGUMENT`] in the following circumstances:
253    /// - There are [too many](Format::max_updates) updates.
254    /// - The updates overlap, i.e. their keys are not disjoint.
255    /// - The updates are invalid, e.g. key [out of bound](Format::max_key) or value [too
256    ///   long](Format::max_value_len).
257    pub fn transaction<ByteSlice: Borrow<[u8]>>(
258        &mut self, updates: &[StoreUpdate<ByteSlice>],
259    ) -> Result<(), Error> {
260        let count = usize_to_nat(updates.len());
261        if count == 0 {
262            return Ok(());
263        }
264        if count == 1 {
265            match updates[0] {
266                StoreUpdate::Insert { key, ref value } => return self.insert(key, value.borrow()),
267                StoreUpdate::Remove { key } => return self.remove(key),
268            }
269        }
270        // Get the sorted keys. Fail if the transaction is invalid.
271        let sorted_keys = match self.format.transaction_valid(updates) {
272            None => return Err(INVALID_ARGUMENT),
273            Some(x) => x,
274        };
275        // Reserve the capacity.
276        self.reserve(self.format.transaction_capacity(updates))?;
277        // Write the marker entry.
278        let marker = self.tail()?;
279        let entry = self.format.build_internal(InternalEntry::Marker { count })?;
280        self.write_slice(marker, &entry)?;
281        self.init_page(marker, marker)?;
282        // Write the updates.
283        let mut tail = marker + 1;
284        for update in updates {
285            let length = match *update {
286                StoreUpdate::Insert { key, ref value } => {
287                    let entry = self.format.build_user(usize_to_nat(key), value.borrow())?;
288                    let word_size = self.format.word_size();
289                    let footer = usize_to_nat(entry.len()) / word_size - 1;
290                    self.write_slice(tail, &entry[.. (footer * word_size) as usize])?;
291                    self.write_slice(tail + footer, &entry[(footer * word_size) as usize ..])?;
292                    footer
293                }
294                StoreUpdate::Remove { key } => {
295                    let key = usize_to_nat(key);
296                    let remove = self.format.build_internal(InternalEntry::Remove { key })?;
297                    self.write_slice(tail, &remove)?;
298                    0
299                }
300            };
301            self.init_page(tail, tail + length)?;
302            tail += 1 + length;
303        }
304        // Apply the transaction.
305        self.transaction_apply(&sorted_keys, marker)
306    }
307
308    /// Removes multiple entries as part of a single transaction.
309    ///
310    /// Entries with a key larger or equal to `min_key` are deleted.
311    pub fn clear(&mut self, min_key: usize) -> Result<(), Error> {
312        let min_key = usize_to_nat(min_key);
313        if min_key > self.format.max_key() {
314            return Err(INVALID_ARGUMENT);
315        }
316        let clear = self.format.build_internal(InternalEntry::Clear { min_key })?;
317        // We always have one word available. We can't use `reserve` because this is internal
318        // capacity, not user capacity.
319        while self.immediate_capacity()? < 1 {
320            self.compact()?;
321        }
322        let tail = self.tail()?;
323        self.write_slice(tail, &clear)?;
324        self.clear_delete(tail)
325    }
326
327    /// Compacts the store once if needed.
328    ///
329    /// If the immediate capacity is at least `length` words, then nothing is modified. Otherwise,
330    /// one page is compacted.
331    pub fn prepare(&mut self, length: usize) -> Result<(), Error> {
332        if self.capacity()?.remaining() < length {
333            return Err(NO_CAPACITY);
334        }
335        if self.immediate_capacity()? < usize_to_nat(length) {
336            self.compact()?;
337        }
338        Ok(())
339    }
340
341    /// Recovers a possible interrupted operation.
342    ///
343    /// If the storage is completely erased, it is initialized.
344    pub fn recover(&mut self) -> Result<(), Error> {
345        self.recover_initialize()?;
346        self.recover_erase()?;
347        self.recover_compaction()?;
348        self.recover_operation()?;
349        Ok(())
350    }
351
352    /// Returns the value of an entry given its key.
353    pub fn find(&self, key: usize) -> Result<Option<Vec<u8>>, Error> {
354        Ok(match self.find_handle(key)? {
355            None => None,
356            Some(handle) => Some(self.get_value(&handle)?),
357        })
358    }
359
360    /// Returns a handle to an entry given its key.
361    pub fn find_handle(&self, key: usize) -> Result<Option<StoreHandle>, Error> {
362        let key = usize_to_nat(key);
363        for handle in self.iter()? {
364            let handle = handle?;
365            if handle.key == key {
366                return Ok(Some(handle));
367            }
368        }
369        Ok(None)
370    }
371
372    /// Inserts an entry in the store.
373    ///
374    /// If an entry for the same key is already present, it is replaced.
375    pub fn insert(&mut self, key: usize, value: &[u8]) -> Result<(), Error> {
376        // NOTE: This (and transaction) could take a position hint on the value to delete.
377        let key = usize_to_nat(key);
378        let value_len = usize_to_nat(value.len());
379        if key > self.format.max_key() || value_len > self.format.max_value_len() {
380            return Err(INVALID_ARGUMENT);
381        }
382        let entry = self.format.build_user(key, value)?;
383        let entry_len = usize_to_nat(entry.len());
384        self.reserve(entry_len / self.format.word_size())?;
385        let tail = self.tail()?;
386        let word_size = self.format.word_size();
387        let footer = entry_len / word_size - 1;
388        self.write_slice(tail, &entry[.. (footer * word_size) as usize])?;
389        self.write_slice(tail + footer, &entry[(footer * word_size) as usize ..])?;
390        self.push_entry(tail)?;
391        self.insert_init(tail, footer, key)
392    }
393
394    /// Removes an entry given its key.
395    ///
396    /// This is not an error if there is no entry for this key.
397    pub fn remove(&mut self, key: usize) -> Result<(), Error> {
398        let key = usize_to_nat(key);
399        if key > self.format.max_key() {
400            return Err(INVALID_ARGUMENT);
401        }
402        self.delete_keys(&[key], self.tail()?)
403    }
404
405    /// Removes an entry given a handle.
406    pub fn remove_handle(&mut self, handle: &StoreHandle) -> Result<(), Error> {
407        self.check_handle(handle)?;
408        self.delete_pos(handle.pos, self.format.bytes_to_words(handle.len))?;
409        self.remove_entry(handle.pos)
410    }
411
412    /// Returns the maximum length in bytes of a value.
413    pub fn max_value_length(&self) -> usize {
414        self.format.max_value_len() as usize
415    }
416
417    /// Returns the length of the value of an entry given its handle.
418    fn get_length(&self, handle: &StoreHandle) -> Result<usize, Error> {
419        self.check_handle(handle)?;
420        let mut pos = handle.pos;
421        match self.parse_entry(&mut pos)? {
422            ParsedEntry::User(header) => Ok(header.length as usize),
423            ParsedEntry::Padding => Err(INVALID_ARGUMENT),
424            _ => Err(INVALID_STORAGE),
425        }
426    }
427
428    /// Returns the value of an entry given its handle.
429    fn get_value(&self, handle: &StoreHandle) -> Result<Vec<u8>, Error> {
430        self.check_handle(handle)?;
431        let mut pos = handle.pos;
432        match self.parse_entry(&mut pos)? {
433            ParsedEntry::User(header) => {
434                let mut result = self.read_slice(handle.pos + 1, header.length);
435                if header.flipped {
436                    let last_byte = result.len() - 1;
437                    result[last_byte] = 0xff;
438                }
439                Ok(result)
440            }
441            ParsedEntry::Padding => Err(INVALID_ARGUMENT),
442            _ => Err(INVALID_STORAGE),
443        }
444    }
445
446    /// Initializes the storage if completely erased or partially initialized.
447    fn recover_initialize(&mut self) -> Result<(), Error> {
448        let word_size = self.format.word_size();
449        for page in 0 .. self.format.num_pages() {
450            let content = self.read_page(page);
451            let (init, rest) = content.split_at(word_size as usize);
452            if (page > 0 && !is_erased(init)) || !is_erased(rest) {
453                return Ok(());
454            }
455        }
456        let index = self.format.index_init(0);
457        let init_info = self.format.build_init(InitInfo { cycle: 0, prefix: 0 })?;
458        self.storage_write_slice(index, &init_info)
459    }
460
461    /// Recovers a possible compaction interrupted while erasing the page.
462    fn recover_erase(&mut self) -> Result<(), Error> {
463        let mut pos = self.get_extremum_page_head(Ordering::Greater)?;
464        let end = pos.next_page(&self.format);
465        while pos < end {
466            let entry_pos = pos;
467            match self.parse_entry(&mut pos)? {
468                ParsedEntry::Internal(InternalEntry::Erase { .. }) => {
469                    return self.compact_erase(entry_pos);
470                }
471                ParsedEntry::Padding | ParsedEntry::User(_) => (),
472                _ => break,
473            }
474        }
475        Ok(())
476    }
477
478    /// Recovers a possible compaction interrupted while copying the entries.
479    fn recover_compaction(&mut self) -> Result<(), Error> {
480        let head = self.get_extremum_page_head(Ordering::Less)?;
481        self.head = Some(head);
482        let head_page = head.page(&self.format);
483        match self.parse_compact(head_page)? {
484            WordState::Erased => Ok(()),
485            WordState::Partial => self.compact(),
486            WordState::Valid(_) => self.compact_copy(),
487        }
488    }
489
490    /// Recover a possible interrupted operation which is not a compaction.
491    fn recover_operation(&mut self) -> Result<(), Error> {
492        self.entries = Some(Vec::new());
493        let mut pos = self.head.ok_or(INVALID_STORAGE)?;
494        let mut prev_pos = pos;
495        let end = pos + self.format.window_size();
496        while pos < end {
497            let entry_pos = pos;
498            match self.parse_entry(&mut pos)? {
499                ParsedEntry::Tail => break,
500                ParsedEntry::User(_) => self.push_entry(entry_pos)?,
501                ParsedEntry::Padding => {
502                    self.wipe_span(entry_pos + 1, pos - entry_pos - 1)?;
503                }
504                ParsedEntry::Internal(InternalEntry::Erase { .. }) => {
505                    return Err(INVALID_STORAGE);
506                }
507                ParsedEntry::Internal(InternalEntry::Clear { .. }) => {
508                    return self.clear_delete(entry_pos);
509                }
510                ParsedEntry::Internal(InternalEntry::Marker { .. }) => {
511                    return self.recover_transaction(entry_pos, end);
512                }
513                ParsedEntry::Internal(InternalEntry::Remove { .. }) => {
514                    self.set_padding(entry_pos)?;
515                }
516                ParsedEntry::Partial => {
517                    return self.recover_wipe_partial(entry_pos, pos - entry_pos - 1);
518                }
519                ParsedEntry::PartialUser => {
520                    return self.recover_delete_user(entry_pos, pos - entry_pos - 1);
521                }
522            }
523            prev_pos = entry_pos;
524        }
525        pos = prev_pos;
526        if let ParsedEntry::User(header) = self.parse_entry(&mut pos)? {
527            self.insert_init(prev_pos, pos - prev_pos - 1, header.key)?;
528        }
529        Ok(())
530    }
531
532    /// Recovers a possible interrupted transaction.
533    fn recover_transaction(&mut self, marker: Position, end: Position) -> Result<(), Error> {
534        let mut pos = marker;
535        let count = match self.parse_entry(&mut pos)? {
536            ParsedEntry::Internal(InternalEntry::Marker { count }) => count,
537            _ => return Err(INVALID_STORAGE),
538        };
539        let sorted_keys = self.recover_transaction_keys(count, pos, end)?;
540        match usize_to_nat(sorted_keys.len()).cmp(&count) {
541            Ordering::Less => (),
542            Ordering::Equal => return self.transaction_apply(&sorted_keys, marker),
543            Ordering::Greater => return Err(INVALID_STORAGE),
544        }
545        while pos < end {
546            let entry_pos = pos;
547            match self.parse_entry(&mut pos)? {
548                ParsedEntry::Tail => break,
549                ParsedEntry::Padding => (),
550                ParsedEntry::User(_) => {
551                    self.delete_pos(entry_pos, pos - entry_pos - 1)?;
552                }
553                ParsedEntry::Internal(InternalEntry::Remove { .. }) => {
554                    self.set_padding(entry_pos)?;
555                }
556                ParsedEntry::Partial => {
557                    self.recover_wipe_partial(entry_pos, pos - entry_pos - 1)?;
558                    break;
559                }
560                ParsedEntry::PartialUser => {
561                    self.recover_delete_user(entry_pos, pos - entry_pos - 1)?;
562                    break;
563                }
564                ParsedEntry::Internal(InternalEntry::Erase { .. })
565                | ParsedEntry::Internal(InternalEntry::Clear { .. })
566                | ParsedEntry::Internal(InternalEntry::Marker { .. }) => {
567                    return Err(INVALID_STORAGE);
568                }
569            }
570        }
571        self.init_page(marker, marker)?;
572        self.set_padding(marker)?;
573        Ok(())
574    }
575
576    /// Returns the domain of a possible interrupted transaction.
577    ///
578    /// The domain is returned as a sorted list of keys.
579    fn recover_transaction_keys(
580        &mut self, count: Nat, mut pos: Position, end: Position,
581    ) -> Result<Vec<Nat>, Error> {
582        let mut sorted_keys = Vec::with_capacity(count as usize);
583        let mut prev_pos = pos;
584        while pos < end {
585            let entry_pos = pos;
586            let key = match self.parse_entry(&mut pos)? {
587                ParsedEntry::Tail
588                | ParsedEntry::Padding
589                | ParsedEntry::Partial
590                | ParsedEntry::PartialUser => break,
591                ParsedEntry::User(header) => header.key,
592                ParsedEntry::Internal(InternalEntry::Remove { key }) => key,
593                ParsedEntry::Internal(_) => return Err(INVALID_STORAGE),
594            };
595            match sorted_keys.binary_search(&key) {
596                Ok(_) => return Err(INVALID_STORAGE),
597                Err(pos) => sorted_keys.insert(pos, key),
598            }
599            prev_pos = entry_pos;
600        }
601        pos = prev_pos;
602        match self.parse_entry(&mut pos)? {
603            ParsedEntry::User(_) | ParsedEntry::Internal(InternalEntry::Remove { .. }) => {
604                let length = pos - prev_pos - 1;
605                self.init_page(prev_pos, prev_pos + length)?;
606            }
607            _ => (),
608        }
609        Ok(sorted_keys)
610    }
611
612    /// Completes a possible partial entry wipe.
613    fn recover_wipe_partial(&mut self, pos: Position, length: Nat) -> Result<(), Error> {
614        self.wipe_span(pos + 1, length)?;
615        self.init_page(pos, pos + length)?;
616        self.set_padding(pos)?;
617        Ok(())
618    }
619
620    /// Completes a possible partial entry deletion.
621    fn recover_delete_user(&mut self, pos: Position, length: Nat) -> Result<(), Error> {
622        self.init_page(pos, pos + length)?;
623        self.delete_pos(pos, length)
624    }
625
626    /// Checks that a handle still points in the current window.
627    ///
628    /// In particular, the handle has not been compacted.
629    fn check_handle(&self, handle: &StoreHandle) -> Result<(), Error> {
630        if handle.pos < self.head.ok_or(INVALID_STORAGE)? { Err(INVALID_ARGUMENT) } else { Ok(()) }
631    }
632
633    /// Compacts the store as needed.
634    ///
635    /// If there is at least `length` words of remaining capacity, pages are compacted until that
636    /// amount is immediately available.
637    fn reserve(&mut self, length: Nat) -> Result<(), Error> {
638        if self.capacity()?.remaining() < length as usize {
639            return Err(NO_CAPACITY);
640        }
641        while self.immediate_capacity()? < length {
642            self.compact()?;
643        }
644        Ok(())
645    }
646
647    /// Continues an entry insertion after it has been written.
648    fn insert_init(&mut self, pos: Position, length: Nat, key: Nat) -> Result<(), Error> {
649        self.init_page(pos, pos + length)?;
650        self.delete_keys(&[key], pos)?;
651        Ok(())
652    }
653
654    /// Compacts one page.
655    fn compact(&mut self) -> Result<(), Error> {
656        let head = self.head.ok_or(INVALID_STORAGE)?;
657        if head.cycle(&self.format) >= self.format.max_page_erases() {
658            return Err(NO_LIFETIME);
659        }
660        let tail = max(self.tail()?, head.next_page(&self.format));
661        let index = self.format.index_compact(head.page(&self.format));
662        let compact_info = self.format.build_compact(CompactInfo { tail: tail - head })?;
663        self.storage_write_slice(index, &compact_info)?;
664        self.compact_copy()
665    }
666
667    /// Continues a compaction after its compact page info has been written.
668    fn compact_copy(&mut self) -> Result<(), Error> {
669        let mut head = self.head.ok_or(INVALID_STORAGE)?;
670        let page = head.page(&self.format);
671        let end = head.next_page(&self.format);
672        let mut tail = match self.parse_compact(page)? {
673            WordState::Valid(CompactInfo { tail }) => head + tail,
674            _ => return Err(INVALID_STORAGE),
675        };
676        if tail < end {
677            return Err(INVALID_STORAGE);
678        }
679        while head < end {
680            let pos = head;
681            match self.parse_entry(&mut head)? {
682                ParsedEntry::Tail => break,
683                // This can happen if we copy to the next page. We actually reached the tail but we
684                // read what we just copied.
685                ParsedEntry::Partial if head > end => break,
686                ParsedEntry::User(_) => (),
687                ParsedEntry::Padding => continue,
688                _ => return Err(INVALID_STORAGE),
689            };
690            let length = head - pos;
691            // We have to copy the slice to work around the lifetime without using unsafe.
692            let entry = self.read_slice(pos, length * self.format.word_size());
693            self.remove_entry(pos)?;
694            self.write_slice(tail, &entry)?;
695            self.push_entry(tail)?;
696            self.init_page(tail, tail + (length - 1))?;
697            tail += length;
698        }
699        let erase = self.format.build_internal(InternalEntry::Erase { page })?;
700        self.write_slice(tail, &erase)?;
701        self.init_page(tail, tail)?;
702        self.compact_erase(tail)
703    }
704
705    /// Continues a compaction after its erase entry has been written.
706    fn compact_erase(&mut self, erase: Position) -> Result<(), Error> {
707        // Read the page to erase from the erase entry.
708        let mut page = match self.parse_entry(&mut erase.clone())? {
709            ParsedEntry::Internal(InternalEntry::Erase { page }) => page,
710            _ => return Err(INVALID_STORAGE),
711        };
712        // Erase the page.
713        self.storage_erase_page(page)?;
714        // Update the head.
715        page = (page + 1) % self.format.num_pages();
716        let init = match self.parse_init(page)? {
717            WordState::Valid(x) => x,
718            _ => return Err(INVALID_STORAGE),
719        };
720        let head = self.format.page_head(init, page);
721        if let Some(entries) = &mut self.entries {
722            let head_offset = u16::try_from(head - self.head.ok_or(INVALID_STORAGE)?)
723                .map_err(|_| INVALID_STORAGE)?;
724            for entry in entries {
725                *entry = entry.checked_sub(head_offset).ok_or(INVALID_STORAGE)?;
726            }
727        }
728        self.head = Some(head);
729        // Wipe the overlapping entry from the erased page.
730        let pos = head.page_begin(&self.format);
731        self.wipe_span(pos, head - pos)?;
732        // Mark the erase entry as done.
733        self.set_padding(erase)?;
734        Ok(())
735    }
736
737    /// Continues a transaction after it has been written.
738    fn transaction_apply(&mut self, sorted_keys: &[Nat], marker: Position) -> Result<(), Error> {
739        self.delete_keys(sorted_keys, marker)?;
740        self.set_padding(marker)?;
741        let end = self.head.ok_or(INVALID_STORAGE)? + self.format.window_size();
742        let mut pos = marker + 1;
743        while pos < end {
744            let entry_pos = pos;
745            match self.parse_entry(&mut pos)? {
746                ParsedEntry::Tail => break,
747                ParsedEntry::User(_) => self.push_entry(entry_pos)?,
748                ParsedEntry::Internal(InternalEntry::Remove { .. }) => {
749                    self.set_padding(entry_pos)?
750                }
751                _ => return Err(INVALID_STORAGE),
752            }
753        }
754        Ok(())
755    }
756
757    /// Continues a clear operation after its internal entry has been written.
758    fn clear_delete(&mut self, clear: Position) -> Result<(), Error> {
759        self.init_page(clear, clear)?;
760        let min_key = match self.parse_entry(&mut clear.clone())? {
761            ParsedEntry::Internal(InternalEntry::Clear { min_key }) => min_key,
762            _ => return Err(INVALID_STORAGE),
763        };
764        self.delete_if(clear, |key| key >= min_key)?;
765        self.set_padding(clear)?;
766        Ok(())
767    }
768
769    /// Deletes a set of entries up to a certain position.
770    fn delete_keys(&mut self, sorted_keys: &[Nat], end: Position) -> Result<(), Error> {
771        self.delete_if(end, |key| sorted_keys.binary_search(&key).is_ok())
772    }
773
774    /// Deletes entries matching a predicate up to a certain position.
775    fn delete_if(&mut self, end: Position, delete: impl Fn(Nat) -> bool) -> Result<(), Error> {
776        let head = self.head.ok_or(INVALID_STORAGE)?;
777        let mut entries = self.entries.take().ok_or(INVALID_STORAGE)?;
778        let mut i = 0;
779        while i < entries.len() {
780            let pos = head + entries[i] as Nat;
781            if pos >= end {
782                break;
783            }
784            let header = match self.parse_entry(&mut pos.clone())? {
785                ParsedEntry::User(x) => x,
786                _ => return Err(INVALID_STORAGE),
787            };
788            if delete(header.key) {
789                self.delete_pos(pos, self.format.bytes_to_words(header.length))?;
790                entries.swap_remove(i);
791            } else {
792                i += 1;
793            }
794        }
795        self.entries = Some(entries);
796        Ok(())
797    }
798
799    /// Deletes the entry at a given position.
800    fn delete_pos(&mut self, pos: Position, length: Nat) -> Result<(), Error> {
801        self.set_deleted(pos)?;
802        self.wipe_span(pos + 1, length)?;
803        Ok(())
804    }
805
806    /// Writes the init info of a page between 2 positions if needed.
807    ///
808    /// The positions should designate the first and last word of an entry. The init info of the
809    /// highest page is written in any of the following conditions:
810    /// - The entry starts at the beginning of a virtual page.
811    /// - The entry spans 2 pages.
812    fn init_page(&mut self, first: Position, last: Position) -> Result<(), Error> {
813        debug_assert!(first <= last);
814        debug_assert!(last - first < self.format.virt_page_size());
815        let new_first = if first.word(&self.format) == 0 {
816            first
817        } else if first.page(&self.format) == last.page(&self.format) {
818            return Ok(());
819        } else {
820            last + 1
821        };
822        let page = new_first.page(&self.format);
823        if let WordState::Valid(_) = self.parse_init(page)? {
824            return Ok(());
825        }
826        let index = self.format.index_init(page);
827        let init_info = self.format.build_init(InitInfo {
828            cycle: new_first.cycle(&self.format),
829            prefix: new_first.word(&self.format),
830        })?;
831        self.storage_write_slice(index, &init_info)?;
832        Ok(())
833    }
834
835    /// Sets the padding bit of a user header.
836    fn set_padding(&mut self, pos: Position) -> Result<(), Error> {
837        let mut word = Word::from_slice(&self.read_word(pos));
838        self.format.set_padding(&mut word)?;
839        self.write_slice(pos, &word.as_slice())?;
840        Ok(())
841    }
842
843    /// Sets the deleted bit of a user header.
844    fn set_deleted(&mut self, pos: Position) -> Result<(), Error> {
845        let mut word = Word::from_slice(&self.read_word(pos));
846        self.format.set_deleted(&mut word);
847        self.write_slice(pos, &word.as_slice())?;
848        Ok(())
849    }
850
851    /// Wipes a slice of words.
852    fn wipe_span(&mut self, pos: Position, length: Nat) -> Result<(), Error> {
853        let length = (length * self.format.word_size()) as usize;
854        self.write_slice(pos, &vec![0x00; length])
855    }
856
857    /// Returns an extremum page.
858    ///
859    /// With `Greater` returns the most recent page (or the tail). With `Less` returns the oldest
860    /// page (or the head).
861    fn get_extremum_page_head(&self, ordering: Ordering) -> Result<Position, Error> {
862        let mut best = None;
863        for page in 0 .. self.format.num_pages() {
864            let init = match self.parse_init(page)? {
865                WordState::Valid(x) => x,
866                _ => continue,
867            };
868            let pos = self.format.page_head(init, page);
869            if best.is_none_or(|x| pos.cmp(&x) == ordering) {
870                best = Some(pos);
871            }
872        }
873        // There is always at least one initialized page.
874        best.ok_or(INVALID_STORAGE)
875    }
876
877    /// Returns the number of words that can be written without compaction.
878    fn immediate_capacity(&self) -> Result<Nat, Error> {
879        let tail = self.tail()?;
880        let end = self.head.ok_or(INVALID_STORAGE)? + self.format.virt_size();
881        Ok(end.get().saturating_sub(tail.get()))
882    }
883
884    /// Returns the position of the first word in the store.
885    #[cfg(feature = "std")]
886    pub(crate) fn head(&self) -> Result<Position, Error> {
887        self.head.ok_or(INVALID_STORAGE)
888    }
889
890    /// Returns one past the position of the last word in the store.
891    pub(crate) fn tail(&self) -> Result<Position, Error> {
892        let mut pos = self.get_extremum_page_head(Ordering::Greater)?;
893        let end = pos.next_page(&self.format);
894        while pos < end {
895            if let ParsedEntry::Tail = self.parse_entry(&mut pos)? {
896                break;
897            }
898        }
899        Ok(pos)
900    }
901
902    fn push_entry(&mut self, pos: Position) -> Result<(), Error> {
903        let entries = match &mut self.entries {
904            None => return Ok(()),
905            Some(x) => x,
906        };
907        let head = self.head.ok_or(INVALID_STORAGE)?;
908        let offset = u16::try_from(pos - head).map_err(|_| INVALID_STORAGE)?;
909        debug_assert!(!entries.contains(&offset));
910        entries.push(offset);
911        Ok(())
912    }
913
914    fn remove_entry(&mut self, pos: Position) -> Result<(), Error> {
915        let entries = match &mut self.entries {
916            None => return Ok(()),
917            Some(x) => x,
918        };
919        let head = self.head.ok_or(INVALID_STORAGE)?;
920        let offset = u16::try_from(pos - head).map_err(|_| INVALID_STORAGE)?;
921        let i = entries.iter().position(|x| *x == offset).ok_or(INVALID_STORAGE)?;
922        entries.swap_remove(i);
923        Ok(())
924    }
925
926    /// Parses the entry at a given position.
927    ///
928    /// The position is updated to point to the next entry.
929    fn parse_entry(&self, pos: &mut Position) -> Result<ParsedEntry, Error> {
930        let valid = match self.parse_word(*pos)? {
931            WordState::Erased | WordState::Partial => return Ok(self.parse_partial(pos)),
932            WordState::Valid(x) => x,
933        };
934        Ok(match valid {
935            ParsedWord::Padding(Padding { length }) => {
936                *pos += 1 + length;
937                ParsedEntry::Padding
938            }
939            ParsedWord::Header(header) if header.length > self.format.max_value_len() => {
940                self.parse_partial(pos)
941            }
942            ParsedWord::Header(header) => {
943                let length = self.format.bytes_to_words(header.length);
944                let footer = match length {
945                    0 => None,
946                    _ => Some(self.read_word(*pos + length)),
947                };
948                if header.check(footer.as_deref()) {
949                    if header.key > self.format.max_key() {
950                        return Err(INVALID_STORAGE);
951                    }
952                    *pos += 1 + length;
953                    ParsedEntry::User(header)
954                } else if footer.is_none_or(|x| is_erased(&x)) {
955                    self.parse_partial(pos)
956                } else {
957                    *pos += 1 + length;
958                    ParsedEntry::PartialUser
959                }
960            }
961            ParsedWord::Internal(internal) => {
962                *pos += 1;
963                ParsedEntry::Internal(internal)
964            }
965        })
966    }
967
968    /// Parses a possible partial user entry.
969    ///
970    /// This does look ahead past the header and possible erased word in case words near the end of
971    /// the entry were written first.
972    fn parse_partial(&self, pos: &mut Position) -> ParsedEntry {
973        let mut length = None;
974        for i in 0 .. self.format.max_prefix_len() {
975            if !is_erased(&self.read_word(*pos + i)) {
976                length = Some(i);
977            }
978        }
979        match length {
980            None => ParsedEntry::Tail,
981            Some(length) => {
982                *pos += 1 + length;
983                ParsedEntry::Partial
984            }
985        }
986    }
987
988    /// Parses the init info of a page.
989    fn parse_init(&self, page: Nat) -> Result<WordState<InitInfo>, Error> {
990        let index = self.format.index_init(page);
991        let word = self.storage_read_slice(index, self.format.word_size());
992        self.format.parse_init(Word::from_slice(&word))
993    }
994
995    /// Parses the compact info of a page.
996    fn parse_compact(&self, page: Nat) -> Result<WordState<CompactInfo>, Error> {
997        let index = self.format.index_compact(page);
998        let word = self.storage_read_slice(index, self.format.word_size());
999        self.format.parse_compact(Word::from_slice(&word))
1000    }
1001
1002    /// Parses a word from the virtual storage.
1003    fn parse_word(&self, pos: Position) -> Result<WordState<ParsedWord>, Error> {
1004        self.format.parse_word(Word::from_slice(&self.read_word(pos)))
1005    }
1006
1007    /// Reads a slice from the virtual storage.
1008    ///
1009    /// The slice may span 2 pages.
1010    fn read_slice(&self, pos: Position, length: Nat) -> Vec<u8> {
1011        let mut result = Vec::with_capacity(length as usize);
1012        let index = pos.index(&self.format);
1013        let max_length = self.format.page_size() - usize_to_nat(index.byte);
1014        result.extend_from_slice(&self.storage_read_slice(index, min(length, max_length)));
1015        if length > max_length {
1016            // The slice spans the next page.
1017            let index = pos.next_page(&self.format).index(&self.format);
1018            result.extend_from_slice(&self.storage_read_slice(index, length - max_length));
1019        }
1020        result
1021    }
1022
1023    /// Reads a word from the virtual storage.
1024    fn read_word(&self, pos: Position) -> Cow<'_, [u8]> {
1025        self.storage_read_slice(pos.index(&self.format), self.format.word_size())
1026    }
1027
1028    /// Reads a physical page.
1029    fn read_page(&self, page: Nat) -> Cow<'_, [u8]> {
1030        let index = StorageIndex { page: page as usize, byte: 0 };
1031        self.storage_read_slice(index, self.format.page_size())
1032    }
1033
1034    /// Reads a slice from the physical storage.
1035    fn storage_read_slice(&self, index: StorageIndex, length: Nat) -> Cow<'_, [u8]> {
1036        // The only possible failures are if the slice spans multiple pages.
1037        self.storage.read_slice(index, length as usize).unwrap()
1038    }
1039
1040    /// Writes a slice to the virtual storage.
1041    ///
1042    /// The slice may span 2 pages.
1043    fn write_slice(&mut self, pos: Position, value: &[u8]) -> Result<(), Error> {
1044        let index = pos.index(&self.format);
1045        let max_length = (self.format.page_size() - usize_to_nat(index.byte)) as usize;
1046        self.storage_write_slice(index, &value[.. min(value.len(), max_length)])?;
1047        if value.len() > max_length {
1048            // The slice spans the next page.
1049            let index = pos.next_page(&self.format).index(&self.format);
1050            self.storage_write_slice(index, &value[max_length ..])?;
1051        }
1052        Ok(())
1053    }
1054
1055    /// Writes a slice to the physical storage.
1056    ///
1057    /// Only starts writing the slice from the first word that needs to be written (because it
1058    /// differs from the current value).
1059    fn storage_write_slice(&mut self, index: StorageIndex, value: &[u8]) -> Result<(), Error> {
1060        let word_size = self.format.word_size();
1061        debug_assert!(usize_to_nat(value.len()).is_multiple_of(word_size));
1062        let slice = self.storage.read_slice(index, value.len()).map_err(Error::pop)?;
1063        // Skip as many words that don't need to be written as possible.
1064        for start in (0 .. usize_to_nat(value.len())).step_by(word_size as usize) {
1065            if is_write_needed(
1066                &slice[start as usize ..][.. word_size as usize],
1067                &value[start as usize ..][.. word_size as usize],
1068            )? {
1069                // We must write the remaining slice.
1070                let index = StorageIndex {
1071                    page: index.page,
1072                    byte: (usize_to_nat(index.byte) + start) as usize,
1073                };
1074                let value = &value[start as usize ..];
1075                self.storage.write_slice(index, value).map_err(Error::pop)?;
1076                break;
1077            }
1078        }
1079        // There is nothing remaining to write.
1080        Ok(())
1081    }
1082
1083    /// Erases a page if not already erased.
1084    fn storage_erase_page(&mut self, page: Nat) -> Result<(), Error> {
1085        if !is_erased(&self.read_page(page)) {
1086            self.storage.erase_page(page as usize).map_err(Error::pop)?;
1087        }
1088        Ok(())
1089    }
1090}
1091
1092// Those functions are not meant for production.
1093#[cfg(feature = "std")]
1094impl Store<BufferStorage> {
1095    /// Returns the storage configuration.
1096    pub fn format(&self) -> &Format {
1097        &self.format
1098    }
1099
1100    /// Accesses the storage.
1101    pub fn storage(&self) -> &BufferStorage {
1102        &self.storage
1103    }
1104
1105    /// Accesses the storage mutably.
1106    pub fn storage_mut(&mut self) -> &mut BufferStorage {
1107        &mut self.storage
1108    }
1109
1110    /// Returns the value of a possibly deleted entry.
1111    ///
1112    /// If the value has been partially compacted, only return the non-compacted part. Returns an
1113    /// empty value if it has been fully compacted.
1114    pub fn inspect_value(&self, handle: &StoreHandle) -> Vec<u8> {
1115        let head = self.head.unwrap();
1116        let length = self.format.bytes_to_words(handle.len);
1117        if head <= handle.pos {
1118            // The value has not been compacted.
1119            self.read_slice(handle.pos + 1, handle.len)
1120        } else if (handle.pos + length).page(&self.format) == head.page(&self.format) {
1121            // The value has been partially compacted.
1122            let next_page = handle.pos.next_page(&self.format);
1123            let erased_len = (next_page - (handle.pos + 1)) * self.format.word_size();
1124            self.read_slice(next_page, handle.len - erased_len)
1125        } else {
1126            // The value has been fully compacted.
1127            Vec::new()
1128        }
1129    }
1130
1131    /// Applies an operation and returns the deleted entries.
1132    ///
1133    /// Note that the deleted entries are before any compaction, so they may point outside the
1134    /// window. This is more expressive than returning the deleted entries after compaction since
1135    /// compaction can be controlled independently.
1136    pub fn apply(&mut self, operation: &StoreOperation) -> (Vec<StoreHandle>, Result<(), Error>) {
1137        let deleted = |store: &Store<BufferStorage>, delete_key: &dyn Fn(usize) -> bool| {
1138            store
1139                .iter()
1140                .unwrap()
1141                .filter(|x| x.is_err() || delete_key(x.as_ref().unwrap().key as usize))
1142                .collect::<Result<Vec<_>, _>>()
1143        };
1144        match *operation {
1145            StoreOperation::Transaction { ref updates } => {
1146                let keys: HashSet<usize> = updates.iter().map(|x| x.key()).collect();
1147                match deleted(self, &|key| keys.contains(&key)) {
1148                    Ok(deleted) => (deleted, self.transaction(updates)),
1149                    Err(error) => (Vec::new(), Err(error)),
1150                }
1151            }
1152            StoreOperation::Clear { min_key } => match deleted(self, &|key| key >= min_key) {
1153                Ok(deleted) => (deleted, self.clear(min_key)),
1154                Err(error) => (Vec::new(), Err(error)),
1155            },
1156            StoreOperation::Prepare { length } => (Vec::new(), self.prepare(length)),
1157        }
1158    }
1159
1160    /// Initializes an erased storage as if it has been erased `cycle` times.
1161    pub fn init_with_cycle(storage: &mut BufferStorage, cycle: usize) {
1162        let format = Format::new(storage).unwrap();
1163        // Write the init info of the first page.
1164        let mut index = format.index_init(0);
1165        let init_info =
1166            format.build_init(InitInfo { cycle: usize_to_nat(cycle), prefix: 0 }).unwrap();
1167        storage.write_slice(index, &init_info).unwrap();
1168        // Pad the first word of the page. This makes the store looks used, otherwise we may confuse
1169        // it with a partially initialized store.
1170        index.byte += 2 * format.word_size() as usize;
1171        storage.write_slice(index, &vec![0; format.word_size() as usize]).unwrap();
1172        // Inform the storage that the pages have been used.
1173        for page in 0 .. storage.num_pages() {
1174            storage.set_page_erases(page, cycle);
1175        }
1176    }
1177}
1178
1179/// Represents an entry in the store.
1180#[derive(Debug)]
1181enum ParsedEntry {
1182    /// Padding entry.
1183    ///
1184    /// This can be any of the following:
1185    /// - A deleted user entry.
1186    /// - A completed internal entry.
1187    /// - A wiped partial entry.
1188    Padding,
1189
1190    /// Non-deleted user entry.
1191    User(Header),
1192
1193    /// Internal entry.
1194    Internal(InternalEntry),
1195
1196    /// Partial user entry with non-erased footer.
1197    ///
1198    /// The fact that the footer is not erased and does not checksum, means that the header is
1199    /// valid. In particular, the length is valid. We cannot wipe the entry because wiping the
1200    /// footer may validate the checksum. So we mark the entry as deleted, which also wipes it.
1201    PartialUser,
1202
1203    /// Partial entry.
1204    ///
1205    /// This can be any of the following:
1206    /// - A partial user entry with erased footer.
1207    /// - A partial user entry with invalid length.
1208    Partial,
1209
1210    /// End of entries.
1211    ///
1212    /// In particular this is where the next entry will be written.
1213    Tail,
1214}
1215
1216/// Returns whether 2 slices are different.
1217///
1218/// Returns an error if `target` has a bit set to one for which `source` is set to zero.
1219fn is_write_needed(source: &[u8], target: &[u8]) -> Result<bool, Error> {
1220    debug_assert_eq!(source.len(), target.len());
1221    for (&source, &target) in source.iter().zip(target.iter()) {
1222        if source & target != target {
1223            return Err(INVALID_STORAGE);
1224        }
1225        if source != target {
1226            return Ok(true);
1227        }
1228    }
1229    Ok(false)
1230}
1231
1232#[cfg(test)]
1233mod tests {
1234    use super::*;
1235    use crate::test::MINIMAL;
1236
1237    #[test]
1238    fn is_write_needed_ok() {
1239        assert_eq!(is_write_needed(&[], &[]), Ok(false));
1240        assert_eq!(is_write_needed(&[0], &[0]), Ok(false));
1241        assert_eq!(is_write_needed(&[0], &[1]), Err(INVALID_STORAGE));
1242        assert_eq!(is_write_needed(&[1], &[0]), Ok(true));
1243        assert_eq!(is_write_needed(&[1], &[1]), Ok(false));
1244    }
1245
1246    #[test]
1247    fn init_ok() {
1248        assert!(MINIMAL.new_driver().power_on().is_ok());
1249    }
1250
1251    #[test]
1252    fn insert_ok() {
1253        let mut driver = MINIMAL.new_driver().power_on().unwrap();
1254        // Empty entry.
1255        driver.insert(0, &[]).unwrap();
1256        driver.insert(1, &[]).unwrap();
1257        driver.check().unwrap();
1258        // Last word is erased but last bit is not user data.
1259        driver.insert(0, &[0xff]).unwrap();
1260        driver.insert(1, &[0xff]).unwrap();
1261        driver.check().unwrap();
1262        // Last word is erased and last bit is user data.
1263        driver.insert(0, &[0xff, 0xff, 0xff, 0xff]).unwrap();
1264        driver.insert(1, &[0xff, 0xff, 0xff, 0xff]).unwrap();
1265        driver.insert(2, &[0x5c; 6]).unwrap();
1266        driver.check().unwrap();
1267        // Entry spans 2 pages.
1268        assert_eq!(driver.store().tail().unwrap().get(), 13);
1269        driver.insert(3, &[0x5c; 8]).unwrap();
1270        driver.check().unwrap();
1271        assert_eq!(driver.store().tail().unwrap().get(), 16);
1272        // Entry ends a page.
1273        driver.insert(2, &[0x93; (28 - 16 - 1) * 4]).unwrap();
1274        driver.check().unwrap();
1275        assert_eq!(driver.store().tail().unwrap().get(), 28);
1276        // Entry starts a page.
1277        driver.insert(3, &[0x81; 10]).unwrap();
1278        driver.check().unwrap();
1279    }
1280
1281    #[test]
1282    fn remove_ok() {
1283        let mut driver = MINIMAL.new_driver().power_on().unwrap();
1284        // Remove absent entry.
1285        driver.remove(0).unwrap();
1286        driver.remove(1).unwrap();
1287        driver.check().unwrap();
1288        // Remove last inserted entry.
1289        driver.insert(0, &[0x5c; 6]).unwrap();
1290        driver.remove(0).unwrap();
1291        driver.check().unwrap();
1292        // Remove empty entries.
1293        driver.insert(0, &[]).unwrap();
1294        driver.insert(1, &[]).unwrap();
1295        driver.remove(0).unwrap();
1296        driver.remove(1).unwrap();
1297        driver.check().unwrap();
1298        // Remove entry with flipped bit.
1299        driver.insert(0, &[0xff]).unwrap();
1300        driver.insert(1, &[0xff; 4]).unwrap();
1301        driver.remove(0).unwrap();
1302        driver.remove(1).unwrap();
1303        driver.check().unwrap();
1304        // Write some entries with one spanning 2 pages.
1305        driver.insert(2, &[0x93; 9]).unwrap();
1306        assert_eq!(driver.store().tail().unwrap().get(), 13);
1307        driver.insert(3, &[0x81; 10]).unwrap();
1308        assert_eq!(driver.store().tail().unwrap().get(), 17);
1309        driver.insert(4, &[0x76; 11]).unwrap();
1310        driver.check().unwrap();
1311        // Remove the entry spanning 2 pages.
1312        driver.remove(3).unwrap();
1313        driver.check().unwrap();
1314        // Write some entries with one ending a page and one starting the next.
1315        assert_eq!(driver.store().tail().unwrap().get(), 21);
1316        driver.insert(2, &[0xd7; (28 - 21 - 1) * 4]).unwrap();
1317        assert_eq!(driver.store().tail().unwrap().get(), 28);
1318        driver.insert(4, &[0xe2; 21]).unwrap();
1319        driver.check().unwrap();
1320        // Remove them.
1321        driver.remove(2).unwrap();
1322        driver.remove(4).unwrap();
1323        driver.check().unwrap();
1324    }
1325
1326    #[test]
1327    fn prepare_ok() {
1328        let mut driver = MINIMAL.new_driver().power_on().unwrap();
1329
1330        // Don't compact if enough immediate capacity.
1331        assert_eq!(driver.store().immediate_capacity().unwrap(), 39);
1332        assert_eq!(driver.store().capacity().unwrap().remaining(), 34);
1333        assert_eq!(driver.store().head().unwrap().get(), 0);
1334        driver.store_mut().prepare(34).unwrap();
1335        assert_eq!(driver.store().head().unwrap().get(), 0);
1336
1337        // Fill the store.
1338        for key in 0 .. 4 {
1339            driver.insert(key, &[0x38; 28]).unwrap();
1340        }
1341        driver.check().unwrap();
1342        assert_eq!(driver.store().immediate_capacity().unwrap(), 7);
1343        assert_eq!(driver.store().capacity().unwrap().remaining(), 2);
1344        // Removing entries increases available capacity but not immediate capacity.
1345        driver.remove(0).unwrap();
1346        driver.remove(2).unwrap();
1347        driver.check().unwrap();
1348        assert_eq!(driver.store().immediate_capacity().unwrap(), 7);
1349        assert_eq!(driver.store().capacity().unwrap().remaining(), 18);
1350
1351        // Prepare for next write (7 words data + 1 word overhead).
1352        assert_eq!(driver.store().head().unwrap().get(), 0);
1353        driver.store_mut().prepare(8).unwrap();
1354        driver.check().unwrap();
1355        assert_eq!(driver.store().head().unwrap().get(), 16);
1356        // The available capacity did not change, but the immediate capacity is above 8.
1357        assert_eq!(driver.store().immediate_capacity().unwrap(), 14);
1358        assert_eq!(driver.store().capacity().unwrap().remaining(), 18);
1359    }
1360
1361    #[test]
1362    fn reboot_ok() {
1363        let mut driver = MINIMAL.new_driver().power_on().unwrap();
1364
1365        // Do some operations and reboot.
1366        driver.insert(0, &[0x38; 24]).unwrap();
1367        driver.insert(1, &[0x5c; 13]).unwrap();
1368        driver = driver.power_off().power_on().unwrap();
1369        driver.check().unwrap();
1370
1371        // Do more operations and reboot.
1372        driver.insert(2, &[0x93; 1]).unwrap();
1373        driver.remove(0).unwrap();
1374        driver.insert(3, &[0xde; 9]).unwrap();
1375        driver = driver.power_off().power_on().unwrap();
1376        driver.check().unwrap();
1377    }
1378
1379    #[test]
1380    fn entries_ok() {
1381        let mut driver = MINIMAL.new_driver().power_on().unwrap();
1382
1383        // The store is initially empty.
1384        assert!(driver.store().entries.as_ref().unwrap().is_empty());
1385
1386        // Inserted elements are added.
1387        const LEN: usize = 6;
1388        driver.insert(0, &[0x38; (LEN - 1) * 4]).unwrap();
1389        driver.insert(1, &[0x5c; 4]).unwrap();
1390        assert_eq!(driver.store().entries, Some(vec![0, LEN as u16]));
1391
1392        // Deleted elements are removed.
1393        driver.remove(0).unwrap();
1394        assert_eq!(driver.store().entries, Some(vec![LEN as u16]));
1395    }
1396}