miden_protocol/account/component/storage/schema/
map_slot.rs1use alloc::boxed::Box;
2use alloc::collections::BTreeMap;
3use alloc::string::String;
4use alloc::vec::Vec;
5
6use miden_core::utils::{ByteReader, ByteWriter, Deserializable, Serializable};
7use miden_processor::DeserializationError;
8
9use super::super::{InitStorageData, StorageValueName};
10use super::{WordSchema, parse_storage_value_with_schema, validate_description_ascii};
11use crate::Word;
12use crate::account::{StorageMap, StorageMapKey, StorageSlotName};
13use crate::errors::ComponentMetadataError;
14
15#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct MapSlotSchema {
21 description: Option<String>,
22 default_values: Option<BTreeMap<Word, Word>>,
23 key_schema: WordSchema,
24 value_schema: WordSchema,
25}
26
27impl MapSlotSchema {
28 pub fn new(
29 description: Option<String>,
30 default_values: Option<BTreeMap<Word, Word>>,
31 key_schema: WordSchema,
32 value_schema: WordSchema,
33 ) -> Self {
34 Self {
35 description,
36 default_values,
37 key_schema,
38 value_schema,
39 }
40 }
41
42 pub fn description(&self) -> Option<&String> {
43 self.description.as_ref()
44 }
45
46 pub fn try_build_map(
51 &self,
52 init_storage_data: &InitStorageData,
53 slot_name: &StorageSlotName,
54 ) -> Result<StorageMap, ComponentMetadataError> {
55 let mut entries = self.default_values.clone().unwrap_or_default();
56 let slot_prefix = StorageValueName::from_slot_name(slot_name);
57
58 if init_storage_data.slot_value_entry(slot_name).is_some() {
59 return Err(ComponentMetadataError::InvalidInitStorageValue(
60 slot_prefix,
61 "expected a map, got a value".into(),
62 ));
63 }
64 if init_storage_data.has_field_entries_for_slot(slot_name) {
65 return Err(ComponentMetadataError::InvalidInitStorageValue(
66 slot_prefix,
67 "expected a map, got field entries".into(),
68 ));
69 }
70 if let Some(init_entries) = init_storage_data.map_entries(slot_name) {
71 let mut parsed_entries = Vec::with_capacity(init_entries.len());
72 for (raw_key, raw_value) in init_entries.iter() {
73 let key = parse_storage_value_with_schema(&self.key_schema, raw_key, &slot_prefix)?;
74 let value =
75 parse_storage_value_with_schema(&self.value_schema, raw_value, &slot_prefix)?;
76
77 parsed_entries.push((key, value));
78 }
79
80 for (key, value) in parsed_entries.iter() {
81 entries.insert(*key, *value);
82 }
83 }
84
85 if entries.is_empty() {
86 return Ok(StorageMap::new());
87 }
88
89 StorageMap::with_entries(
90 entries.into_iter().map(|(key, value)| (StorageMapKey::from_raw(key), value)),
91 )
92 .map_err(|err| ComponentMetadataError::StorageMapHasDuplicateKeys(Box::new(err)))
93 }
94
95 pub fn key_schema(&self) -> &WordSchema {
96 &self.key_schema
97 }
98
99 pub fn value_schema(&self) -> &WordSchema {
100 &self.value_schema
101 }
102
103 pub fn default_values(&self) -> Option<BTreeMap<Word, Word>> {
104 self.default_values.clone()
105 }
106
107 pub(super) fn write_into_with_optional_defaults<W: ByteWriter>(
108 &self,
109 target: &mut W,
110 include_defaults: bool,
111 ) {
112 target.write(&self.description);
113 let default_values = if include_defaults {
114 self.default_values.clone()
115 } else {
116 None
117 };
118 target.write(&default_values);
119 self.key_schema.write_into_with_optional_defaults(target, include_defaults);
120 self.value_schema.write_into_with_optional_defaults(target, include_defaults);
121 }
122
123 pub(super) fn validate(&self) -> Result<(), ComponentMetadataError> {
124 if let Some(description) = self.description.as_deref() {
125 validate_description_ascii(description)?;
126 }
127 self.key_schema.validate()?;
128 self.value_schema.validate()?;
129 Ok(())
130 }
131}
132
133impl Serializable for MapSlotSchema {
134 fn write_into<W: ByteWriter>(&self, target: &mut W) {
135 self.write_into_with_optional_defaults(target, true);
136 }
137}
138
139impl Deserializable for MapSlotSchema {
140 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
141 let description = Option::<String>::read_from(source)?;
142 let default_values = Option::<BTreeMap<Word, Word>>::read_from(source)?;
143 let key_schema = WordSchema::read_from(source)?;
144 let value_schema = WordSchema::read_from(source)?;
145 Ok(MapSlotSchema::new(description, default_values, key_schema, value_schema))
146 }
147}