arb_storage/
vector.rs

1use revm::Database;
2
3use crate::{backed_types::StorageBackedUint64, storage::Storage};
4
5const LENGTH_OFFSET: u64 = 0;
6
7/// A vector of sub-storages backed by ArbOS storage.
8///
9/// Layout: offset 0 = length, sub-storages at indices 0..length.
10pub struct SubStorageVector<D> {
11    storage: Storage<D>,
12    length: StorageBackedUint64<D>,
13}
14
15pub fn open_sub_storage_vector<D: Database>(storage: Storage<D>) -> SubStorageVector<D> {
16    let state = storage.state_ptr();
17    let base_key = storage.base_key();
18    SubStorageVector {
19        length: StorageBackedUint64::new(state, base_key, LENGTH_OFFSET),
20        storage,
21    }
22}
23
24impl<D: Database> SubStorageVector<D> {
25    pub fn length(&self) -> Result<u64, ()> {
26        self.length.get()
27    }
28
29    /// Returns the sub-storage at the given index.
30    pub fn at(&self, index: u64) -> Storage<D> {
31        self.storage.open_sub_storage(&index.to_be_bytes())
32    }
33
34    /// Appends a new sub-storage and returns it.
35    pub fn push(&self) -> Result<Storage<D>, ()> {
36        let len = self.length.get()?;
37        self.length.set(len + 1)?;
38        Ok(self.at(len))
39    }
40
41    /// Removes the last sub-storage and returns its index.
42    pub fn pop(&self) -> Result<Option<u64>, ()> {
43        let len = self.length.get()?;
44        if len == 0 {
45            return Ok(None);
46        }
47        let new_len = len - 1;
48        self.length.set(new_len)?;
49        Ok(Some(new_len))
50    }
51}