ic_storage/adapter/log.rs
1//! Governed log collection implementation.
2use super::{LogIter, LogWriteError, Memory, Storable};
3use crate::substrate::{self, DefaultMemoryImpl};
4use ic_memory::RuntimeMemory;
5
6/// Governed upstream `Log`; initialization and failures follow upstream contracts.
7pub struct StableLog<T: Storable, M: Memory = DefaultMemoryImpl> {
8 inner: substrate::Log<T, RuntimeMemory<M>, RuntimeMemory<M>>,
9}
10impl<T: Storable, M: Memory> StableLog<T, M> {
11 /// Create a new collection, replacing any prior collection in the selected memory.
12 /// This is destructive even when a valid collection already exists.
13 ///
14 /// # Panics
15 /// Panics on insufficient memory or codec/backing failure.
16 pub fn new(index_memory: RuntimeMemory<M>, data_memory: RuntimeMemory<M>) -> Self {
17 Self {
18 inner: substrate::Log::new(index_memory, data_memory),
19 }
20 }
21 /// Open a retained log, or initialize both memories when data memory is
22 /// empty or has foreign magic. The latter overwrites previous contents.
23 ///
24 /// # Panics
25 /// With recognized data magic, panics for an invalid index or unsupported
26 /// layout. Growth and codec/backing failures also retain upstream panics.
27 pub fn init(index_memory: RuntimeMemory<M>, data_memory: RuntimeMemory<M>) -> Self {
28 Self {
29 inner: substrate::Log::init(index_memory, data_memory),
30 }
31 }
32 /// Delegates to upstream `Log::first` with the governed allocation.
33 pub fn first(&self) -> Option<T> {
34 self.inner.first()
35 }
36 /// Delegates to upstream `Log::last` with the governed allocation.
37 pub fn last(&self) -> Option<T> {
38 self.inner.last()
39 }
40 /// Delegates to upstream `Log::get` with the governed allocation.
41 pub fn get(&self, idx: u64) -> Option<T> {
42 self.inner.get(idx)
43 }
44 /// Delegates to upstream `Log::len` with the governed allocation.
45 pub fn len(&self) -> u64 {
46 self.inner.len()
47 }
48 /// Delegates to upstream `Log::is_empty` with the governed allocation.
49 pub fn is_empty(&self) -> bool {
50 self.inner.is_empty()
51 }
52 /// Delegates to upstream `Log::append` with the governed allocation.
53 /// # Errors
54 /// Returns the upstream write error if memory cannot grow.
55 pub fn append(&self, item: &T) -> Result<u64, LogWriteError> {
56 self.inner.append(item)
57 }
58 /// Delegates to upstream `Log::iter` with the governed allocation.
59 pub fn iter(&self) -> LogIter<'_, T, M> {
60 self.inner.iter()
61 }
62}
63
64impl<'a, T: Storable, M: Memory> IntoIterator for &'a StableLog<T, M> {
65 type Item = T;
66 type IntoIter = LogIter<'a, T, M>;
67 fn into_iter(self) -> Self::IntoIter {
68 self.iter()
69 }
70}