1extern crate alloc;
2
3use miden_field_repr::FromFeltRepr;
4use miden_stdlib_sys::{Felt, Word, felt};
5
6pub fn padded_word_from_felt(value: Felt) -> Word {
8 Word::new([value, felt!(0), felt!(0), felt!(0)])
9}
10
11pub fn felt_from_padded_word(value: Word) -> Result<Felt, &'static str> {
13 if value[1] != felt!(0) || value[2] != felt!(0) || value[3] != felt!(0) {
14 return Err("expected zero padding in the trailing three felts");
15 }
16
17 Ok(value[0])
18}
19
20#[derive(Copy, Clone, Debug, PartialEq, Eq, FromFeltRepr)]
22pub struct AccountId {
23 pub prefix: Felt,
24 pub suffix: Felt,
25}
26
27impl AccountId {
28 pub fn new(prefix: Felt, suffix: Felt) -> Self {
30 Self { prefix, suffix }
31 }
32}
33
34#[derive(Copy, Clone)]
37#[repr(C)]
38pub(crate) struct RawAccountId {
39 pub suffix: Felt,
40 pub prefix: Felt,
41}
42
43impl RawAccountId {
44 pub(crate) fn into_account_id(self) -> AccountId {
46 AccountId::new(self.prefix, self.suffix)
47 }
48}
49
50impl From<AccountId> for Word {
51 #[inline]
52 fn from(value: AccountId) -> Self {
53 Word::from([felt!(0), felt!(0), value.suffix, value.prefix])
54 }
55}
56
57impl TryFrom<Word> for AccountId {
58 type Error = &'static str;
59
60 #[inline]
61 fn try_from(value: Word) -> Result<Self, Self::Error> {
62 if value[0] != felt!(0) || value[1] != felt!(0) {
63 return Err("expected zero padding in the upper two felts");
64 }
65
66 Ok(Self {
67 prefix: value[3],
68 suffix: value[2],
69 })
70 }
71}
72
73#[derive(Copy, Clone, Debug, PartialEq, Eq)]
78#[repr(C)]
79pub struct Asset {
80 pub key: Word,
82 pub value: Word,
84}
85
86impl Asset {
87 pub fn new(key: impl Into<Word>, value: impl Into<Word>) -> Self {
89 Self {
90 key: key.into(),
91 value: value.into(),
92 }
93 }
94}
95
96impl From<Asset> for (Word, Word) {
97 fn from(val: Asset) -> Self {
98 (val.key, val.value)
99 }
100}
101
102#[derive(Clone, Debug, PartialEq, Eq)]
104#[repr(transparent)]
105pub struct Recipient {
106 pub inner: Word,
107}
108
109#[derive(Copy, Clone, Debug, PartialEq, Eq)]
114#[repr(C)]
115pub struct NoteMetadata {
116 pub attachment: Word,
118 pub header: Word,
120}
121
122impl NoteMetadata {
123 pub fn new(attachment: Word, header: Word) -> Self {
125 Self { attachment, header }
126 }
127}
128
129#[derive(Copy, Clone, Debug, PartialEq, Eq)]
131#[repr(C)]
132pub struct AttachmentLocation {
133 pub is_found: Felt,
135 pub index: Felt,
137}
138
139impl AttachmentLocation {
140 #[inline]
142 pub fn found(&self) -> bool {
143 self.is_found != Felt::new(0).unwrap()
144 }
145}
146
147impl From<[Felt; 4]> for Recipient {
148 fn from(value: [Felt; 4]) -> Self {
149 Recipient {
150 inner: Word::from(value),
151 }
152 }
153}
154
155impl From<Word> for Recipient {
156 fn from(value: Word) -> Self {
157 Recipient { inner: value }
158 }
159}
160
161impl From<Recipient> for Word {
162 #[inline]
163 fn from(value: Recipient) -> Self {
164 value.inner
165 }
166}
167
168#[derive(Clone, Copy, Debug, PartialEq, Eq)]
169#[repr(transparent)]
170pub struct Tag {
171 pub inner: Felt,
172}
173
174impl From<Felt> for Tag {
175 fn from(value: Felt) -> Self {
176 Tag { inner: value }
177 }
178}
179
180impl From<Tag> for Word {
181 #[inline]
182 fn from(value: Tag) -> Self {
183 padded_word_from_felt(value.inner)
184 }
185}
186
187impl TryFrom<Word> for Tag {
188 type Error = &'static str;
189
190 #[inline]
191 fn try_from(value: Word) -> Result<Self, Self::Error> {
192 Ok(Tag {
193 inner: felt_from_padded_word(value)?,
194 })
195 }
196}
197
198#[derive(Clone, Copy, Debug, PartialEq, Eq)]
199#[repr(transparent)]
200pub struct NoteIdx {
201 pub inner: Felt,
202}
203
204impl From<NoteIdx> for Word {
205 #[inline]
206 fn from(value: NoteIdx) -> Self {
207 padded_word_from_felt(value.inner)
208 }
209}
210
211impl TryFrom<Word> for NoteIdx {
212 type Error = &'static str;
213
214 #[inline]
215 fn try_from(value: Word) -> Result<Self, Self::Error> {
216 Ok(NoteIdx {
217 inner: felt_from_padded_word(value)?,
218 })
219 }
220}
221
222#[derive(Clone, Copy, Debug, PartialEq, Eq)]
223#[repr(transparent)]
224pub struct NoteType {
225 pub inner: Felt,
226}
227
228impl From<Felt> for NoteType {
229 fn from(value: Felt) -> Self {
230 NoteType { inner: value }
231 }
232}
233
234impl From<NoteType> for Word {
235 #[inline]
236 fn from(value: NoteType) -> Self {
237 padded_word_from_felt(value.inner)
238 }
239}
240
241impl TryFrom<Word> for NoteType {
242 type Error = &'static str;
243
244 #[inline]
245 fn try_from(value: Word) -> Result<Self, Self::Error> {
246 Ok(NoteType {
247 inner: felt_from_padded_word(value)?,
248 })
249 }
250}
251
252#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
259pub struct StorageSlotId {
260 suffix: Felt,
261 prefix: Felt,
262}
263
264impl StorageSlotId {
265 pub fn new(suffix: Felt, prefix: Felt) -> Self {
270 Self { suffix, prefix }
271 }
272
273 pub fn from_prefix_suffix(prefix: Felt, suffix: Felt) -> Self {
277 Self { suffix, prefix }
278 }
279
280 pub fn to_prefix_suffix(&self) -> (Felt, Felt) {
282 (self.prefix, self.suffix)
283 }
284
285 pub fn to_suffix_prefix(&self) -> (Felt, Felt) {
287 (self.suffix, self.prefix)
288 }
289
290 pub fn suffix(&self) -> Felt {
292 self.suffix
293 }
294
295 pub fn prefix(&self) -> Felt {
297 self.prefix
298 }
299}
300
301#[cfg(test)]
302mod tests {
303 use miden_stdlib_sys::{Word, felt};
304
305 use super::{felt_from_padded_word, padded_word_from_felt};
306
307 #[test]
309 fn padded_word_from_felt_zero_pads_trailing_limbs() {
310 assert_eq!(
311 padded_word_from_felt(felt!(7)),
312 Word::new([felt!(7), felt!(0), felt!(0), felt!(0)])
313 );
314 }
315
316 #[test]
318 fn felt_from_padded_word_rejects_non_zero_padding() {
319 let err =
320 felt_from_padded_word(Word::new([felt!(7), felt!(1), felt!(0), felt!(0)])).unwrap_err();
321
322 assert_eq!(err, "expected zero padding in the trailing three felts");
323 }
324
325 #[test]
327 fn felt_padding_helpers_roundtrip() {
328 let value = felt!(42);
329
330 assert_eq!(felt_from_padded_word(padded_word_from_felt(value)), Ok(value));
331 }
332}