Skip to main content

miden_protocol/account/storage/slot/
slot_content.rs

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