miden_protocol/account/component/storage/toml/
init_storage_data.rs1use alloc::string::{String, ToString};
2
3use serde::Deserialize;
4use thiserror::Error;
5
6use super::super::{
7 InitStorageData,
8 InitStorageDataError as CoreInitStorageDataError,
9 StorageValueName,
10 StorageValueNameError,
11 WordValue,
12};
13use super::RawMapEntrySchema;
14
15impl InitStorageData {
16 pub fn from_toml(toml_str: &str) -> Result<Self, InitStorageDataError> {
37 let table: toml::Table = toml::from_str(toml_str)?;
38 let mut data = InitStorageData::default();
39
40 for (key, value) in table {
41 let name: StorageValueName =
42 key.parse().map_err(InitStorageDataError::InvalidStorageValueName)?;
43
44 match value {
45 toml::Value::Table(nested) => {
48 if nested.is_empty() {
49 return Err(InitStorageDataError::EmptyTable(name.to_string()));
50 }
51 if name.field_name().is_some() {
52 return Err(InitStorageDataError::ExcessiveNesting(name.to_string()));
53 }
54 for (field, field_value) in nested {
55 let field_name =
56 StorageValueName::from_slot_name_with_suffix(name.slot_name(), &field)
57 .map_err(InitStorageDataError::InvalidStorageValueName)?;
58 let word = WordValue::deserialize(field_value).map_err(|_| {
59 InitStorageDataError::InvalidValue(field_name.to_string())
60 })?;
61 data.insert_value(field_name, word)?;
62 }
63 },
64 toml::Value::Array(items)
66 if items.iter().all(|v| matches!(v, toml::Value::Table(_))) =>
67 {
68 if name.field_name().is_some() {
69 return Err(InitStorageDataError::InvalidMapEntryKey(name.to_string()));
70 }
71 for item in items {
72 let entry: RawMapEntrySchema = RawMapEntrySchema::deserialize(item)
74 .map_err(|e| {
75 InitStorageDataError::InvalidMapEntrySchema(e.to_string())
76 })?;
77
78 data.insert_map_entry(name.slot_name().clone(), entry.key, entry.value)?;
79 }
80 },
81 other => {
83 let word = WordValue::deserialize(other)
84 .map_err(|_| InitStorageDataError::InvalidValue(name.to_string()))?;
85 data.insert_value(name, word)?;
86 },
87 }
88 }
89
90 Ok(data)
91 }
92}
93
94#[derive(Debug, Error)]
95pub enum InitStorageDataError {
96 #[error("failed to parse TOML: {0}")]
97 InvalidToml(#[from] toml::de::Error),
98
99 #[error("empty table encountered for key `{0}`")]
100 EmptyTable(String),
101
102 #[error(transparent)]
103 InvalidData(#[from] CoreInitStorageDataError),
104
105 #[error("invalid map entry key `{0}`: map entries must target a slot name")]
106 InvalidMapEntryKey(String),
107
108 #[error("excessive nesting for key `{0}`: only one level of table nesting is allowed")]
109 ExcessiveNesting(String),
110
111 #[error(
112 "invalid input for `{0}`: expected a string, a 4-element string array, or a map entry list"
113 )]
114 InvalidValue(String),
115
116 #[error("invalid storage value name")]
117 InvalidStorageValueName(#[source] StorageValueNameError),
118
119 #[error("invalid map entry: {0}")]
120 InvalidMapEntrySchema(String),
121}