arb_storage/
bytes_storage.rs

1use alloy_primitives::B256;
2use revm::Database;
3
4use crate::storage::Storage;
5
6/// Variable-length byte storage.
7///
8/// Layout: slot 0 = length, slots 1..N = data (32 bytes per slot, left-aligned for last chunk).
9pub struct StorageBackedBytes<D> {
10    storage: Storage<D>,
11}
12
13impl<D: Database> StorageBackedBytes<D> {
14    pub fn new(storage: Storage<D>) -> Self {
15        Self { storage }
16    }
17
18    pub fn get(&self) -> Result<Vec<u8>, ()> {
19        let mut bytes_left = self.storage.get_uint64_by_uint64(0)? as usize;
20        if bytes_left == 0 {
21            return Ok(Vec::new());
22        }
23        let mut ret = Vec::with_capacity(bytes_left);
24        let mut offset = 1u64;
25        while bytes_left >= 32 {
26            let next = self.storage.get_by_uint64(offset)?;
27            ret.extend_from_slice(next.as_slice());
28            bytes_left -= 32;
29            offset += 1;
30        }
31        if bytes_left > 0 {
32            let next = self.storage.get_by_uint64(offset)?;
33            ret.extend_from_slice(&next.as_slice()[32 - bytes_left..]);
34        }
35        Ok(ret)
36    }
37
38    pub fn set(&self, b: &[u8]) -> Result<(), ()> {
39        self.clear()?;
40        self.storage.set_uint64_by_uint64(0, b.len() as u64)?;
41        let mut remaining = b;
42        let mut offset = 1u64;
43        while remaining.len() >= 32 {
44            let mut slot = [0u8; 32];
45            slot.copy_from_slice(&remaining[..32]);
46            self.storage.set_by_uint64(offset, B256::from(slot))?;
47            remaining = &remaining[32..];
48            offset += 1;
49        }
50        if !remaining.is_empty() {
51            // Right-align remaining bytes.
52            let mut slot = [0u8; 32];
53            slot[32 - remaining.len()..].copy_from_slice(remaining);
54            self.storage.set_by_uint64(offset, B256::from(slot))?;
55        }
56        Ok(())
57    }
58
59    pub fn clear(&self) -> Result<(), ()> {
60        let bytes_left = self.storage.get_uint64_by_uint64(0)?;
61        let mut offset = 1u64;
62        let mut remaining = bytes_left;
63        while remaining > 0 {
64            self.storage.set_by_uint64(offset, B256::ZERO)?;
65            offset += 1;
66            remaining = remaining.saturating_sub(32);
67        }
68        self.storage.set_uint64_by_uint64(0, 0)?;
69        Ok(())
70    }
71
72    pub fn size(&self) -> Result<u64, ()> {
73        self.storage.get_uint64_by_uint64(0)
74    }
75}
76
77impl<D> Clone for StorageBackedBytes<D> {
78    fn clone(&self) -> Self {
79        Self {
80            storage: self.storage.clone(),
81        }
82    }
83}