miden_base/types/
storage.rs1use miden_base_sys::bindings::{
2 AssetAmount, StorageSlotId, felt_from_padded_word, padded_word_from_felt, storage,
3};
4use miden_stdlib_sys::{Digest, Felt, Word};
5
6pub trait WordValue: Sized {
11 fn try_into_word(self) -> Result<Word, &'static str>;
13
14 fn try_from_word(word: Word) -> Result<Self, &'static str>;
16}
17
18impl WordValue for Word {
19 fn try_into_word(self) -> Result<Word, &'static str> {
20 Ok(self)
21 }
22
23 fn try_from_word(word: Word) -> Result<Self, &'static str> {
24 Ok(word)
25 }
26}
27
28impl WordValue for Felt {
29 fn try_into_word(self) -> Result<Word, &'static str> {
30 Ok(padded_word_from_felt(self))
31 }
32
33 fn try_from_word(word: Word) -> Result<Self, &'static str> {
34 felt_from_padded_word(word)
35 }
36}
37
38impl WordValue for AssetAmount {
39 fn try_into_word(self) -> Result<Word, &'static str> {
40 let amount = AssetAmount::try_from(self.as_felt())
43 .map_err(|_| "asset amount exceeds the maximum allowed amount")?;
44 Ok(padded_word_from_felt(amount.into()))
45 }
46
47 fn try_from_word(word: Word) -> Result<Self, &'static str> {
48 AssetAmount::try_from(felt_from_padded_word(word)?)
49 .map_err(|_| "asset amount exceeds the maximum allowed amount")
50 }
51}
52
53impl WordValue for Digest {
54 fn try_into_word(self) -> Result<Word, &'static str> {
55 Ok(self.into())
56 }
57
58 fn try_from_word(word: Word) -> Result<Self, &'static str> {
59 Ok(word.try_into().unwrap())
60 }
61}
62
63impl WordValue for miden_base_sys::bindings::AccountId {
64 fn try_into_word(self) -> Result<Word, &'static str> {
65 Ok(self.into())
66 }
67
68 fn try_from_word(word: Word) -> Result<Self, &'static str> {
69 word.try_into()
70 }
71}
72
73impl WordValue for miden_base_sys::bindings::Recipient {
74 fn try_into_word(self) -> Result<Word, &'static str> {
75 Ok(self.into())
76 }
77
78 fn try_from_word(word: Word) -> Result<Self, &'static str> {
79 Ok(word.into())
80 }
81}
82
83impl WordValue for miden_base_sys::bindings::Tag {
84 fn try_into_word(self) -> Result<Word, &'static str> {
85 Ok(self.into())
86 }
87
88 fn try_from_word(word: Word) -> Result<Self, &'static str> {
89 word.try_into()
90 }
91}
92
93impl WordValue for miden_base_sys::bindings::NoteIdx {
94 fn try_into_word(self) -> Result<Word, &'static str> {
95 Ok(self.into())
96 }
97
98 fn try_from_word(word: Word) -> Result<Self, &'static str> {
99 word.try_into()
100 }
101}
102
103impl WordValue for miden_base_sys::bindings::NoteType {
104 fn try_into_word(self) -> Result<Word, &'static str> {
105 Ok(self.into())
106 }
107
108 fn try_from_word(word: Word) -> Result<Self, &'static str> {
109 word.try_into()
110 }
111}
112
113pub trait WordKey: Copy {
118 fn try_into_word(self) -> Result<Word, &'static str>;
120}
121
122impl WordKey for Word {
123 fn try_into_word(self) -> Result<Word, &'static str> {
124 Ok(self)
125 }
126}
127
128impl WordKey for Felt {
129 fn try_into_word(self) -> Result<Word, &'static str> {
130 Ok(padded_word_from_felt(self))
131 }
132}
133
134impl WordKey for AssetAmount {
135 fn try_into_word(self) -> Result<Word, &'static str> {
136 let amount = AssetAmount::try_from(self.as_felt())
139 .map_err(|_| "asset amount exceeds the maximum allowed amount")?;
140 Ok(padded_word_from_felt(amount.into()))
141 }
142}
143
144impl WordKey for miden_base_sys::bindings::AccountId {
145 fn try_into_word(self) -> Result<Word, &'static str> {
146 Ok(self.into())
147 }
148}
149
150impl WordKey for miden_base_sys::bindings::Tag {
151 fn try_into_word(self) -> Result<Word, &'static str> {
152 Ok(self.into())
153 }
154}
155
156impl WordKey for miden_base_sys::bindings::NoteIdx {
157 fn try_into_word(self) -> Result<Word, &'static str> {
158 Ok(self.into())
159 }
160}
161
162impl WordKey for miden_base_sys::bindings::NoteType {
163 fn try_into_word(self) -> Result<Word, &'static str> {
164 Ok(self.into())
165 }
166}
167
168#[derive(Debug, Copy, Clone, PartialEq, Eq)]
170pub struct StorageValue<T: WordValue> {
171 pub slot: StorageSlotId,
173 _marker: core::marker::PhantomData<T>,
174}
175
176impl<T: WordValue> StorageValue<T> {
177 pub const fn new(slot: StorageSlotId) -> Self {
179 Self {
180 slot,
181 _marker: core::marker::PhantomData,
182 }
183 }
184}
185
186impl<T: WordValue> From<StorageSlotId> for StorageValue<T> {
187 fn from(slot: StorageSlotId) -> Self {
188 Self::new(slot)
189 }
190}
191
192impl<T: WordValue> StorageValue<T> {
193 #[inline(always)]
195 pub fn get(&self) -> T {
196 T::try_from_word(storage::get_item(self.slot))
197 .unwrap_or_else(|_| panic!("storage slot {:?} contained an invalid word", self.slot))
198 }
199
200 #[inline(always)]
202 pub fn set(&mut self, value: T) -> T {
203 let value = value
204 .try_into_word()
205 .unwrap_or_else(|_| panic!("failed to convert value for storage slot {:?}", self.slot));
206 T::try_from_word(storage::set_item(self.slot, value))
207 .unwrap_or_else(|_| panic!("storage slot {:?} contained an invalid word", self.slot))
208 }
209}
210
211#[derive(Debug, Copy, Clone, PartialEq, Eq)]
213pub struct StorageMap<K: WordKey, V: WordValue> {
214 pub slot: StorageSlotId,
216 _marker: core::marker::PhantomData<(K, V)>,
217}
218
219impl<K: WordKey, V: WordValue> StorageMap<K, V> {
220 pub const fn new(slot: StorageSlotId) -> Self {
222 Self {
223 slot,
224 _marker: core::marker::PhantomData,
225 }
226 }
227}
228
229impl<K: WordKey, V: WordValue> From<StorageSlotId> for StorageMap<K, V> {
230 fn from(slot: StorageSlotId) -> Self {
231 Self::new(slot)
232 }
233}
234
235impl<K: WordKey, V: WordValue> StorageMap<K, V> {
236 #[inline(always)]
241 pub fn get(&self, key: K) -> V {
242 let key = key.try_into_word().unwrap_or_else(|_| {
243 panic!("failed to convert key for storage map slot {:?}", self.slot)
244 });
245 V::try_from_word(storage::get_map_item(self.slot, &key)).unwrap_or_else(|_| {
246 panic!("storage map slot {:?} contained an invalid word", self.slot)
247 })
248 }
249
250 #[inline(always)]
255 pub fn set(&mut self, key: K, value: V) -> V {
256 let key = key.try_into_word().unwrap_or_else(|_| {
257 panic!("failed to convert key for storage map slot {:?}", self.slot)
258 });
259 let value = value.try_into_word().unwrap_or_else(|_| {
260 panic!("failed to convert value for storage map slot {:?}", self.slot)
261 });
262 V::try_from_word(storage::set_map_item(self.slot, key, value)).unwrap_or_else(|_| {
263 panic!("storage map slot {:?} contained an invalid word", self.slot)
264 })
265 }
266}