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