Skip to main content

miden_protocol/account/storage/slot/
slot_content.rs

1use miden_core::EMPTY_WORD;
2
3use crate::account::StorageSlotType;
4use crate::account::storage::map::EMPTY_STORAGE_MAP_ROOT;
5use crate::account::storage::{StorageMap, Word};
6use crate::utils::serde::{
7    ByteReader,
8    ByteWriter,
9    Deserializable,
10    DeserializationError,
11    Serializable,
12};
13
14// STORAGE SLOT CONTENT
15// ================================================================================================
16
17/// Represents the contents of a [`StorageSlot`](super::StorageSlot).
18///
19/// The content of a storage slot can be of two types:
20/// - A simple value which contains a single word (4 field elements or ~32 bytes).
21/// - A key value map where both keys and values are words. The capacity of such storage slot is
22///   theoretically unlimited.
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum StorageSlotContent {
25    Value(Word),
26    Map(StorageMap),
27}
28
29impl StorageSlotContent {
30    /// Returns true if this storage slot has a value equal to the default of its type.
31    pub fn is_default(&self) -> bool {
32        match self {
33            StorageSlotContent::Value(value) => *value == EMPTY_WORD,
34            StorageSlotContent::Map(map) => map.root() == EMPTY_STORAGE_MAP_ROOT,
35        }
36    }
37
38    /// Returns the empty [Word] for a storage slot of this type
39    pub fn default_word(&self) -> Word {
40        match self {
41            StorageSlotContent::Value(_) => EMPTY_WORD,
42            StorageSlotContent::Map(_) => EMPTY_STORAGE_MAP_ROOT,
43        }
44    }
45
46    /// Returns a [`StorageSlotContent::Value`] with an empty word.
47    pub fn empty_value() -> Self {
48        StorageSlotContent::Value(EMPTY_WORD)
49    }
50
51    /// Returns an empty [`StorageSlotContent::Map`].
52    pub fn empty_map() -> Self {
53        StorageSlotContent::Map(StorageMap::new())
54    }
55
56    /// Returns this storage slot value as a [Word]
57    ///
58    /// Returns:
59    /// - For [`StorageSlotContent::Value`] the value.
60    /// - For [`StorageSlotContent::Map`] the root of the [StorageMap].
61    pub fn value(&self) -> Word {
62        match self {
63            Self::Value(value) => *value,
64            Self::Map(map) => map.root(),
65        }
66    }
67
68    /// Returns the type of this storage slot
69    pub fn slot_type(&self) -> StorageSlotType {
70        match self {
71            StorageSlotContent::Value(_) => StorageSlotType::Value,
72            StorageSlotContent::Map(_) => StorageSlotType::Map,
73        }
74    }
75}
76
77// SERIALIZATION
78// ================================================================================================
79
80impl Serializable for StorageSlotContent {
81    fn write_into<W: ByteWriter>(&self, target: &mut W) {
82        target.write(self.slot_type());
83
84        match self {
85            Self::Value(value) => target.write(value),
86            Self::Map(map) => target.write(map),
87        }
88    }
89
90    fn get_size_hint(&self) -> usize {
91        let mut size = self.slot_type().get_size_hint();
92
93        size += match self {
94            StorageSlotContent::Value(word) => word.get_size_hint(),
95            StorageSlotContent::Map(storage_map) => storage_map.get_size_hint(),
96        };
97
98        size
99    }
100}
101
102impl Deserializable for StorageSlotContent {
103    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
104        let storage_slot_type = source.read::<StorageSlotType>()?;
105
106        match storage_slot_type {
107            StorageSlotType::Value => {
108                let word = source.read::<Word>()?;
109                Ok(StorageSlotContent::Value(word))
110            },
111            StorageSlotType::Map => {
112                let map = source.read::<StorageMap>()?;
113                Ok(StorageSlotContent::Map(map))
114            },
115        }
116    }
117}
118
119// TESTS
120// ================================================================================================
121
122#[cfg(test)]
123mod tests {
124    use crate::account::AccountStorage;
125    use crate::utils::serde::{Deserializable, Serializable};
126
127    #[test]
128    fn test_serde_storage_slot_content() {
129        let storage = AccountStorage::mock();
130        let serialized = storage.to_bytes();
131        let deserialized = AccountStorage::read_from_bytes(&serialized).unwrap();
132        assert_eq!(deserialized, storage)
133    }
134}