Skip to main content

miden_debug_engine/
felt.rs

1use alloc::{
2    string::{String, ToString},
3    vec::Vec,
4};
5
6use miden_core::{Word, field::PrimeField64};
7pub use miden_processor::Felt as RawFelt;
8#[cfg(feature = "proptest")]
9use proptest::{
10    arbitrary::Arbitrary,
11    strategy::{BoxedStrategy, Strategy},
12};
13use serde::Deserialize;
14use smallvec::{SmallVec, smallvec};
15
16pub trait ToMidenRepr {
17    /// Convert this type into its raw byte representation
18    ///
19    /// The order of bytes in the resulting vector should be little-endian, i.e. the least
20    /// significant bytes come first.
21    fn to_bytes(&self) -> SmallVec<[u8; 16]>;
22    /// Convert this type into one or more field elements, where the order of the elements is such
23    /// that the byte representation of `self` is in little-endian order, i.e. the least significant
24    /// bytes come first.
25    fn to_felts(&self) -> SmallVec<[RawFelt; 4]> {
26        let bytes = self.to_bytes();
27        let num_felts = bytes.len().div_ceil(4);
28        let mut felts = SmallVec::<[RawFelt; 4]>::with_capacity(num_felts);
29        let (chunks, remainder) = bytes.as_chunks::<4>();
30        for chunk in chunks {
31            felts.push(
32                RawFelt::new(u32::from_ne_bytes(*chunk) as u64)
33                    .expect("value exceeds field modulus"),
34            );
35        }
36        if !remainder.is_empty() {
37            let mut chunk = [0u8; 4];
38            for (i, byte) in remainder.iter().enumerate() {
39                chunk[i] = *byte;
40            }
41            felts.push(
42                RawFelt::new(u32::from_ne_bytes(chunk) as u64)
43                    .expect("value exceeds field modulus"),
44            );
45        }
46        felts
47    }
48    /// Convert this type into one or more words, zero-padding as needed, such that:
49    ///
50    /// * The field elements within each word is in little-endian order, i.e. the least significant
51    ///   bytes of come first.
52    /// * Each word, if pushed on the operand stack element-by-element, would leave the element
53    ///   with the most significant bytes on top of the stack (including padding)
54    fn to_words(&self) -> SmallVec<[Word; 1]> {
55        let felts = self.to_felts();
56        let num_words = felts.len().div_ceil(4);
57        let mut words = SmallVec::<[Word; 1]>::with_capacity(num_words);
58        let (chunks, remainder) = felts.as_chunks::<4>();
59        for mut word in chunks.iter().copied() {
60            word.reverse();
61            words.push(Word::new(word));
62        }
63        if !remainder.is_empty() {
64            let mut word = [RawFelt::ZERO; 4];
65            for (i, felt) in remainder.iter().enumerate() {
66                word[i] = *felt;
67            }
68            word.reverse();
69            words.push(Word::new(word));
70        }
71        words
72    }
73
74    /// Push this value on the given operand stack using [Self::to_felts] representation
75    ///
76    /// If pushing arguments for functions compiled from Wasm, consider using
77    /// [`push_wasm_ty_to_operand_stack`] instead.
78    fn push_to_operand_stack(&self, stack: &mut Vec<RawFelt>) {
79        stack.extend(self.to_felts());
80    }
81
82    /// Push this value in its [Self::to_words] representation, on the given stack.
83    ///
84    /// This function is designed for encoding values that will be placed on the advice stack and
85    /// copied into Miden VM memory by the compiler-emitted test harness.
86    ///
87    /// Returns the number of words that were pushed on the stack
88    fn push_words_to_advice_stack(&self, stack: &mut Vec<RawFelt>) -> usize {
89        let words = self.to_words();
90        let num_words = words.len();
91        for word in words.into_iter().rev() {
92            for felt in word.into_iter() {
93                stack.push(felt);
94            }
95        }
96        num_words
97    }
98}
99
100pub trait FromMidenRepr: Sized {
101    /// Returns the size of this type as encoded by [ToMidenRepr::to_felts]
102    fn size_in_felts() -> usize;
103    /// Extract a value of this type from `bytes`, where:
104    ///
105    /// * It is assumed that bytes is always padded out to 4 byte alignment
106    /// * It is assumed that the bytes are in little-endian order, as encoded by [ToMidenRepr]
107    fn from_bytes(bytes: &[u8]) -> Self;
108    /// Extract a value of this type as encoded in a vector of field elements, where:
109    ///
110    /// * The order of the field elements is little-endian, i.e. the element holding the least
111    ///   significant bytes comes first.
112    fn from_felts(felts: &[RawFelt]) -> Self {
113        let mut bytes = SmallVec::<[u8; 16]>::with_capacity(felts.len() * 4);
114        for felt in felts {
115            let chunk = (felt.as_canonical_u64() as u32).to_ne_bytes();
116            bytes.extend(chunk);
117        }
118        Self::from_bytes(&bytes)
119    }
120    /// Extract a value of this type as encoded in a vector of words, where:
121    ///
122    /// * The order of the words is little-endian, i.e. the word holding the least significant
123    ///   bytes comes first.
124    /// * The order of the field elements in each word is in big-endian order, i.e. the element
125    ///   with the most significant byte is at the start of the word, and the element with the
126    ///   least significant byte is at the end of the word. This corresponds to the order in
127    ///   which elements are placed on the operand stack when preparing to read or write them
128    ///   from Miden's memory.
129    fn from_words(words: &[Word]) -> Self {
130        let mut felts = SmallVec::<[RawFelt; 4]>::with_capacity(words.len() * 4);
131        for word in words {
132            for felt in word.iter().copied().rev() {
133                felts.push(felt);
134            }
135        }
136        Self::from_felts(&felts)
137    }
138
139    /// Pop a value of this type from `stack` based on the canonical representation of this type
140    /// on the operand stack when writing it to memory (and as read from memory).
141    fn pop_from_stack(stack: &mut Vec<RawFelt>) -> Self {
142        let needed = Self::size_in_felts();
143        let mut felts = SmallVec::<[RawFelt; 4]>::with_capacity(needed);
144        for _ in 0..needed {
145            felts.push(stack.pop().unwrap());
146        }
147        Self::from_felts(&felts)
148    }
149}
150
151impl ToMidenRepr for bool {
152    fn to_bytes(&self) -> SmallVec<[u8; 16]> {
153        smallvec![*self as u8]
154    }
155
156    fn to_felts(&self) -> SmallVec<[RawFelt; 4]> {
157        smallvec![RawFelt::new(*self as u64).expect("value exceeds field modulus")]
158    }
159
160    fn push_to_operand_stack(&self, stack: &mut Vec<RawFelt>) {
161        stack.push(RawFelt::new(*self as u64).expect("value exceeds field modulus"));
162    }
163}
164
165impl FromMidenRepr for bool {
166    #[inline(always)]
167    fn size_in_felts() -> usize {
168        1
169    }
170
171    fn from_bytes(bytes: &[u8]) -> Self {
172        match bytes[0] {
173            0 => false,
174            1 => true,
175            n => panic!("invalid byte representation for boolean: {n:0x}"),
176        }
177    }
178
179    fn from_felts(felts: &[RawFelt]) -> Self {
180        match felts[0].as_canonical_u64() {
181            0 => false,
182            1 => true,
183            n => panic!("invalid byte representation for boolean: {n:0x}"),
184        }
185    }
186
187    fn pop_from_stack(stack: &mut Vec<RawFelt>) -> Self {
188        match stack.pop().unwrap().as_canonical_u64() {
189            0 => false,
190            1 => true,
191            n => panic!("invalid byte representation for boolean: {n:0x}"),
192        }
193    }
194}
195
196impl ToMidenRepr for u8 {
197    fn to_bytes(&self) -> SmallVec<[u8; 16]> {
198        smallvec![*self]
199    }
200
201    fn to_felts(&self) -> SmallVec<[RawFelt; 4]> {
202        smallvec![RawFelt::new(*self as u64).expect("value exceeds field modulus")]
203    }
204
205    fn push_to_operand_stack(&self, stack: &mut Vec<RawFelt>) {
206        stack.push(RawFelt::new(*self as u64).expect("value exceeds field modulus"));
207    }
208}
209
210impl FromMidenRepr for u8 {
211    #[inline(always)]
212    fn size_in_felts() -> usize {
213        1
214    }
215
216    #[inline(always)]
217    fn from_bytes(bytes: &[u8]) -> Self {
218        bytes[0]
219    }
220
221    fn from_felts(felts: &[RawFelt]) -> Self {
222        felts[0].as_canonical_u64() as u8
223    }
224
225    fn pop_from_stack(stack: &mut Vec<RawFelt>) -> Self {
226        stack.pop().unwrap().as_canonical_u64() as u8
227    }
228}
229
230impl ToMidenRepr for i8 {
231    fn to_bytes(&self) -> SmallVec<[u8; 16]> {
232        smallvec![*self as u8]
233    }
234
235    fn to_felts(&self) -> SmallVec<[RawFelt; 4]> {
236        smallvec![RawFelt::new(*self as u8 as u64).expect("value exceeds field modulus")]
237    }
238
239    fn push_to_operand_stack(&self, stack: &mut Vec<RawFelt>) {
240        stack.push(RawFelt::new(*self as u8 as u64).expect("value exceeds field modulus"));
241    }
242}
243
244impl FromMidenRepr for i8 {
245    #[inline(always)]
246    fn size_in_felts() -> usize {
247        1
248    }
249
250    #[inline(always)]
251    fn from_bytes(bytes: &[u8]) -> Self {
252        bytes[0] as i8
253    }
254
255    fn from_felts(felts: &[RawFelt]) -> Self {
256        felts[0].as_canonical_u64() as u8 as i8
257    }
258
259    fn pop_from_stack(stack: &mut Vec<RawFelt>) -> Self {
260        stack.pop().unwrap().as_canonical_u64() as u8 as i8
261    }
262}
263
264impl ToMidenRepr for u16 {
265    fn to_bytes(&self) -> SmallVec<[u8; 16]> {
266        SmallVec::from_slice(&self.to_ne_bytes())
267    }
268
269    fn to_felts(&self) -> SmallVec<[RawFelt; 4]> {
270        smallvec![RawFelt::new(*self as u64).expect("value exceeds field modulus")]
271    }
272
273    fn push_to_operand_stack(&self, stack: &mut Vec<RawFelt>) {
274        stack.push(RawFelt::new(*self as u64).expect("value exceeds field modulus"));
275    }
276}
277
278impl FromMidenRepr for u16 {
279    #[inline(always)]
280    fn size_in_felts() -> usize {
281        1
282    }
283
284    fn from_bytes(bytes: &[u8]) -> Self {
285        assert!(bytes.len() >= 2);
286        u16::from_ne_bytes([bytes[0], bytes[1]])
287    }
288
289    fn from_felts(felts: &[RawFelt]) -> Self {
290        felts[0].as_canonical_u64() as u16
291    }
292
293    fn pop_from_stack(stack: &mut Vec<RawFelt>) -> Self {
294        stack.pop().unwrap().as_canonical_u64() as u16
295    }
296}
297
298impl ToMidenRepr for i16 {
299    fn to_bytes(&self) -> SmallVec<[u8; 16]> {
300        SmallVec::from_slice(&self.to_ne_bytes())
301    }
302
303    fn to_felts(&self) -> SmallVec<[RawFelt; 4]> {
304        smallvec![RawFelt::new(*self as u16 as u64).expect("value exceeds field modulus")]
305    }
306
307    fn push_to_operand_stack(&self, stack: &mut Vec<RawFelt>) {
308        stack.push(RawFelt::new(*self as u16 as u64).expect("value exceeds field modulus"));
309    }
310}
311
312impl FromMidenRepr for i16 {
313    #[inline(always)]
314    fn size_in_felts() -> usize {
315        1
316    }
317
318    fn from_bytes(bytes: &[u8]) -> Self {
319        assert!(bytes.len() >= 2);
320        i16::from_ne_bytes([bytes[0], bytes[1]])
321    }
322
323    fn from_felts(felts: &[RawFelt]) -> Self {
324        felts[0].as_canonical_u64() as u16 as i16
325    }
326
327    fn pop_from_stack(stack: &mut Vec<RawFelt>) -> Self {
328        stack.pop().unwrap().as_canonical_u64() as u16 as i16
329    }
330}
331
332impl ToMidenRepr for u32 {
333    fn to_bytes(&self) -> SmallVec<[u8; 16]> {
334        SmallVec::from_slice(&self.to_ne_bytes())
335    }
336
337    fn to_felts(&self) -> SmallVec<[RawFelt; 4]> {
338        smallvec![RawFelt::new(*self as u64).expect("value exceeds field modulus")]
339    }
340
341    fn push_to_operand_stack(&self, stack: &mut Vec<RawFelt>) {
342        stack.push(RawFelt::new(*self as u64).expect("value exceeds field modulus"));
343    }
344}
345
346impl FromMidenRepr for u32 {
347    #[inline(always)]
348    fn size_in_felts() -> usize {
349        1
350    }
351
352    fn from_bytes(bytes: &[u8]) -> Self {
353        assert!(bytes.len() >= 4);
354        u32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]])
355    }
356
357    fn from_felts(felts: &[RawFelt]) -> Self {
358        felts[0].as_canonical_u64() as u32
359    }
360
361    fn pop_from_stack(stack: &mut Vec<RawFelt>) -> Self {
362        stack.pop().unwrap().as_canonical_u64() as u32
363    }
364}
365
366impl ToMidenRepr for i32 {
367    fn to_bytes(&self) -> SmallVec<[u8; 16]> {
368        SmallVec::from_slice(&self.to_ne_bytes())
369    }
370
371    fn to_felts(&self) -> SmallVec<[RawFelt; 4]> {
372        smallvec![RawFelt::new(*self as u32 as u64).expect("value exceeds field modulus")]
373    }
374
375    fn push_to_operand_stack(&self, stack: &mut Vec<RawFelt>) {
376        stack.push(RawFelt::new(*self as u32 as u64).expect("value exceeds field modulus"));
377    }
378}
379
380impl FromMidenRepr for i32 {
381    #[inline(always)]
382    fn size_in_felts() -> usize {
383        1
384    }
385
386    fn from_bytes(bytes: &[u8]) -> Self {
387        assert!(bytes.len() >= 4);
388        i32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]])
389    }
390
391    fn from_felts(felts: &[RawFelt]) -> Self {
392        felts[0].as_canonical_u64() as u32 as i32
393    }
394
395    fn pop_from_stack(stack: &mut Vec<RawFelt>) -> Self {
396        stack.pop().unwrap().as_canonical_u64() as u32 as i32
397    }
398}
399
400impl ToMidenRepr for u64 {
401    fn to_bytes(&self) -> SmallVec<[u8; 16]> {
402        SmallVec::from_slice(&self.to_le_bytes())
403    }
404
405    fn to_felts(&self) -> SmallVec<[RawFelt; 4]> {
406        let lo = (*self as u32) as u64;
407        let hi = *self >> 32;
408        smallvec![
409            RawFelt::new(lo).expect("value exceeds field modulus"),
410            RawFelt::new(hi).expect("value exceeds field modulus"),
411        ]
412    }
413}
414
415impl FromMidenRepr for u64 {
416    #[inline(always)]
417    fn size_in_felts() -> usize {
418        2
419    }
420
421    fn from_bytes(bytes: &[u8]) -> Self {
422        assert!(bytes.len() >= 8);
423        u64::from_le_bytes([
424            bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
425        ])
426    }
427
428    fn from_felts(felts: &[RawFelt]) -> Self {
429        assert!(felts.len() >= 2);
430        let lo = felts[0].as_canonical_u64() as u32 as u64;
431        let hi = felts[1].as_canonical_u64() as u32 as u64;
432        lo | (hi << 32)
433    }
434}
435
436impl ToMidenRepr for i64 {
437    fn to_bytes(&self) -> SmallVec<[u8; 16]> {
438        SmallVec::from_slice(&self.to_le_bytes())
439    }
440
441    fn to_felts(&self) -> SmallVec<[RawFelt; 4]> {
442        (*self as u64).to_felts()
443    }
444}
445
446impl FromMidenRepr for i64 {
447    #[inline(always)]
448    fn size_in_felts() -> usize {
449        2
450    }
451
452    fn from_bytes(bytes: &[u8]) -> Self {
453        u64::from_bytes(bytes) as i64
454    }
455
456    fn from_felts(felts: &[RawFelt]) -> Self {
457        u64::from_felts(felts) as i64
458    }
459}
460
461impl ToMidenRepr for u128 {
462    fn to_bytes(&self) -> SmallVec<[u8; 16]> {
463        SmallVec::from_slice(&self.to_le_bytes())
464    }
465
466    fn to_felts(&self) -> SmallVec<[RawFelt; 4]> {
467        let lo_lo = RawFelt::new((*self as u32) as u64).expect("value exceeds field modulus");
468        let lo_hi =
469            RawFelt::new(((*self >> 32) as u32) as u64).expect("value exceeds field modulus");
470        let hi_lo =
471            RawFelt::new(((*self >> 64) as u32) as u64).expect("value exceeds field modulus");
472        let hi_hi =
473            RawFelt::new(((*self >> 96) as u32) as u64).expect("value exceeds field modulus");
474        smallvec![lo_lo, lo_hi, hi_lo, hi_hi]
475    }
476}
477
478impl FromMidenRepr for u128 {
479    #[inline(always)]
480    fn size_in_felts() -> usize {
481        4
482    }
483
484    fn from_bytes(bytes: &[u8]) -> Self {
485        assert!(bytes.len() >= 16);
486        u128::from_le_bytes([
487            bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
488            bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15],
489        ])
490    }
491
492    fn from_felts(felts: &[RawFelt]) -> Self {
493        assert!(felts.len() >= 4);
494        let lo_lo = felts[0].as_canonical_u64() as u32 as u128;
495        let lo_hi = felts[1].as_canonical_u64() as u32 as u128;
496        let hi_lo = felts[2].as_canonical_u64() as u32 as u128;
497        let hi_hi = felts[3].as_canonical_u64() as u32 as u128;
498        lo_lo | (lo_hi << 32) | (hi_lo << 64) | (hi_hi << 96)
499    }
500}
501
502impl ToMidenRepr for i128 {
503    fn to_bytes(&self) -> SmallVec<[u8; 16]> {
504        SmallVec::from_slice(&self.to_le_bytes())
505    }
506
507    fn to_felts(&self) -> SmallVec<[RawFelt; 4]> {
508        (*self as u128).to_felts()
509    }
510}
511
512impl FromMidenRepr for i128 {
513    #[inline(always)]
514    fn size_in_felts() -> usize {
515        4
516    }
517
518    fn from_bytes(bytes: &[u8]) -> Self {
519        u128::from_bytes(bytes) as i128
520    }
521
522    fn from_felts(felts: &[RawFelt]) -> Self {
523        u128::from_felts(felts) as i128
524    }
525}
526
527impl ToMidenRepr for RawFelt {
528    fn to_bytes(&self) -> SmallVec<[u8; 16]> {
529        panic!("field elements have no canonical byte representation")
530    }
531
532    fn to_felts(&self) -> SmallVec<[RawFelt; 4]> {
533        smallvec![*self]
534    }
535
536    fn to_words(&self) -> SmallVec<[Word; 1]> {
537        let mut word = [RawFelt::ZERO; 4];
538        word[0] = *self;
539        smallvec![Word::new(word)]
540    }
541}
542
543impl FromMidenRepr for RawFelt {
544    #[inline(always)]
545    fn size_in_felts() -> usize {
546        1
547    }
548
549    fn from_bytes(_bytes: &[u8]) -> Self {
550        panic!("field elements have no canonical byte representation")
551    }
552
553    #[inline(always)]
554    fn from_felts(felts: &[RawFelt]) -> Self {
555        felts[0]
556    }
557
558    #[inline(always)]
559    fn from_words(words: &[Word]) -> Self {
560        words[0][0]
561    }
562}
563
564impl ToMidenRepr for Felt {
565    fn to_bytes(&self) -> SmallVec<[u8; 16]> {
566        panic!("field elements have no canonical byte representation")
567    }
568
569    fn to_felts(&self) -> SmallVec<[RawFelt; 4]> {
570        smallvec![self.0]
571    }
572
573    fn to_words(&self) -> SmallVec<[Word; 1]> {
574        let mut word = [RawFelt::ZERO; 4];
575        word[0] = self.0;
576        smallvec![Word::new(word)]
577    }
578}
579
580impl FromMidenRepr for Felt {
581    #[inline(always)]
582    fn size_in_felts() -> usize {
583        1
584    }
585
586    fn from_bytes(_bytes: &[u8]) -> Self {
587        panic!("field elements have no canonical byte representation")
588    }
589
590    #[inline(always)]
591    fn from_felts(felts: &[RawFelt]) -> Self {
592        Felt(felts[0])
593    }
594
595    #[inline(always)]
596    fn from_words(words: &[Word]) -> Self {
597        Felt(words[0][0])
598    }
599}
600
601impl<const N: usize> ToMidenRepr for [u8; N] {
602    #[inline]
603    fn to_bytes(&self) -> SmallVec<[u8; 16]> {
604        SmallVec::from_slice(self)
605    }
606}
607
608impl<const N: usize> FromMidenRepr for [u8; N] {
609    #[inline(always)]
610    fn size_in_felts() -> usize {
611        N.div_ceil(4)
612    }
613
614    fn from_bytes(bytes: &[u8]) -> Self {
615        assert!(bytes.len() >= N, "insufficient bytes");
616        Self::try_from(&bytes[..N]).unwrap()
617    }
618}
619
620impl FromMidenRepr for [Felt; 4] {
621    #[inline(always)]
622    fn size_in_felts() -> usize {
623        4
624    }
625
626    fn from_bytes(_bytes: &[u8]) -> Self {
627        panic!("field elements have no canonical byte representation")
628    }
629
630    #[inline(always)]
631    fn from_felts(felts: &[RawFelt]) -> Self {
632        [Felt(felts[0]), Felt(felts[1]), Felt(felts[2]), Felt(felts[3])]
633    }
634}
635
636/// Convert a byte array to an equivalent vector of words
637///
638/// Given a byte slice laid out like so:
639///
640/// [b0, b1, b2, b3, b4, b5, b6, b7, .., b31]
641///
642/// This will produce a vector of words laid out like so:
643///
644/// [[{b12, ..b15}, {b8..b11}, {b4, ..b7}, {b0, ..b3}], [{b31, ..}, ..]]
645///
646/// In short, it produces words that when placed on the stack and written to memory word-by-word,
647/// the original bytes will be laid out in Miden's memory in the correct order.
648pub fn bytes_to_words(bytes: &[u8]) -> Vec<[RawFelt; 4]> {
649    // 1. Chunk bytes up into felts
650    let (chunks, remainder) = bytes.as_chunks::<4>();
651    let padded_bytes = bytes.len().next_multiple_of(16);
652    let num_felts = padded_bytes / 4;
653    let mut buf = Vec::with_capacity(num_felts);
654    for chunk in chunks {
655        let n = u32::from_ne_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
656        buf.push(n);
657    }
658    // Zero-pad the buffer to nearest whole element
659    if !remainder.is_empty() {
660        let mut n_buf = [0u8; 4];
661        for (i, byte) in remainder.iter().enumerate() {
662            n_buf[i] = *byte;
663        }
664        buf.push(u32::from_ne_bytes(n_buf));
665    }
666    // Zero-pad the buffer to nearest whole word
667    buf.resize(num_felts, 0);
668    // Chunk into words, and push them in largest-address first order
669    let num_words = num_felts / 4;
670    let mut words = Vec::with_capacity(num_words);
671    let (chunks, remainder) = buf.as_chunks::<4>();
672    for chunk in chunks {
673        words.push([
674            RawFelt::new(chunk[3] as u64).expect("value exceeds field modulus"),
675            RawFelt::new(chunk[2] as u64).expect("value exceeds field modulus"),
676            RawFelt::new(chunk[1] as u64).expect("value exceeds field modulus"),
677            RawFelt::new(chunk[0] as u64).expect("value exceeds field modulus"),
678        ]);
679    }
680    if !remainder.is_empty() {
681        let mut word = [RawFelt::ZERO; 4];
682        for (i, n) in remainder.iter().enumerate() {
683            word[i] = RawFelt::new(*n as u64).expect("value exceeds field modulus");
684        }
685        word.reverse();
686        words.push(word);
687    }
688    words
689}
690
691/// Wrapper around `miden_processor::Felt` that implements useful traits that are not implemented
692/// for that type.
693#[derive(Debug, Copy, Clone, PartialEq, Eq)]
694pub struct Felt(pub RawFelt);
695impl Felt {
696    #[inline]
697    pub fn new(value: u64) -> Self {
698        Self(RawFelt::new(value).expect("value exceeds field modulus"))
699    }
700}
701
702impl<'de> Deserialize<'de> for Felt {
703    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
704    where
705        D: serde::Deserializer<'de>,
706    {
707        u64::deserialize(deserializer).and_then(|n| {
708            if n >= RawFelt::ORDER_U64 {
709                Err(serde::de::Error::custom(
710                    "invalid field element value: exceeds the field modulus",
711                ))
712            } else {
713                Ok(Felt(RawFelt::new(n).expect("value exceeds field modulus")))
714            }
715        })
716    }
717}
718
719#[cfg(feature = "std")]
720impl clap::builder::ValueParserFactory for Felt {
721    type Parser = FeltParser;
722
723    fn value_parser() -> Self::Parser {
724        FeltParser
725    }
726}
727
728#[doc(hidden)]
729#[cfg(feature = "std")]
730#[derive(Clone)]
731pub struct FeltParser;
732#[cfg(feature = "std")]
733impl clap::builder::TypedValueParser for FeltParser {
734    type Value = Felt;
735
736    fn parse_ref(
737        &self,
738        _cmd: &clap::Command,
739        _arg: Option<&clap::Arg>,
740        value: &std::ffi::OsStr,
741    ) -> Result<Self::Value, clap::error::Error> {
742        use clap::error::{Error, ErrorKind};
743
744        let value = value.to_str().ok_or_else(|| Error::new(ErrorKind::InvalidUtf8))?.trim();
745        value.parse().map_err(|err| Error::raw(ErrorKind::ValueValidation, err))
746    }
747}
748
749impl core::str::FromStr for Felt {
750    type Err = String;
751
752    fn from_str(s: &str) -> Result<Self, Self::Err> {
753        let value = if let Some(value) = s.strip_prefix("0x") {
754            u64::from_str_radix(value, 16)
755                .map_err(|err| format!("invalid field element value: {err}"))?
756        } else {
757            s.parse::<u64>().map_err(|err| format!("invalid field element value: {err}"))?
758        };
759
760        if value >= RawFelt::ORDER_U64 {
761            Err("invalid field element value: exceeds the field modulus".to_string())
762        } else {
763            Ok(Felt(RawFelt::new(value).expect("value exceeds field modulus")))
764        }
765    }
766}
767
768impl From<Felt> for miden_processor::Felt {
769    fn from(f: Felt) -> Self {
770        f.0
771    }
772}
773
774impl From<bool> for Felt {
775    fn from(b: bool) -> Self {
776        Self(RawFelt::new(b as u64).expect("value exceeds field modulus"))
777    }
778}
779
780impl From<u8> for Felt {
781    fn from(t: u8) -> Self {
782        Self(RawFelt::new(t as u64).expect("value exceeds field modulus"))
783    }
784}
785
786impl From<i8> for Felt {
787    fn from(t: i8) -> Self {
788        Self(RawFelt::new(t as u8 as u64).expect("value exceeds field modulus"))
789    }
790}
791
792impl From<i16> for Felt {
793    fn from(t: i16) -> Self {
794        Self(RawFelt::new(t as u16 as u64).expect("value exceeds field modulus"))
795    }
796}
797
798impl From<u16> for Felt {
799    fn from(t: u16) -> Self {
800        Self(RawFelt::new(t as u64).expect("value exceeds field modulus"))
801    }
802}
803
804impl From<i32> for Felt {
805    fn from(t: i32) -> Self {
806        Self(RawFelt::new(t as u32 as u64).expect("value exceeds field modulus"))
807    }
808}
809
810impl From<u32> for Felt {
811    fn from(t: u32) -> Self {
812        Self(RawFelt::new(t as u64).expect("value exceeds field modulus"))
813    }
814}
815
816impl From<u64> for Felt {
817    fn from(t: u64) -> Self {
818        Self(RawFelt::new(t).expect("value exceeds field modulus"))
819    }
820}
821
822impl From<i64> for Felt {
823    fn from(t: i64) -> Self {
824        Self(RawFelt::new(t as u64).expect("value exceeds field modulus"))
825    }
826}
827
828// Reverse Felt to Rust types conversion
829
830impl From<Felt> for bool {
831    fn from(f: Felt) -> Self {
832        f.0.as_canonical_u64() != 0
833    }
834}
835
836impl From<Felt> for u8 {
837    fn from(f: Felt) -> Self {
838        f.0.as_canonical_u64() as u8
839    }
840}
841
842impl From<Felt> for i8 {
843    fn from(f: Felt) -> Self {
844        f.0.as_canonical_u64() as i8
845    }
846}
847
848impl From<Felt> for u16 {
849    fn from(f: Felt) -> Self {
850        f.0.as_canonical_u64() as u16
851    }
852}
853
854impl From<Felt> for i16 {
855    fn from(f: Felt) -> Self {
856        f.0.as_canonical_u64() as i16
857    }
858}
859
860impl From<Felt> for u32 {
861    fn from(f: Felt) -> Self {
862        f.0.as_canonical_u64() as u32
863    }
864}
865
866impl From<Felt> for i32 {
867    fn from(f: Felt) -> Self {
868        f.0.as_canonical_u64() as i32
869    }
870}
871
872impl From<Felt> for u64 {
873    fn from(f: Felt) -> Self {
874        f.0.as_canonical_u64()
875    }
876}
877
878impl From<Felt> for i64 {
879    fn from(f: Felt) -> Self {
880        f.0.as_canonical_u64() as i64
881    }
882}
883
884#[cfg(feature = "proptest")]
885impl Arbitrary for Felt {
886    type Parameters = ();
887    type Strategy = BoxedStrategy<Self>;
888
889    fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
890        (0u64..RawFelt::ORDER_U64)
891            .prop_map(|v| Felt(RawFelt::new(v).expect("value exceeds field modulus")))
892            .boxed()
893    }
894}
895
896/// Converts `value` to its corresponding Wasm ABI type and pushes it to the stack.
897///
898/// It differs from [`ToMidenRepr::push_to_operand_stack`] because it sign-extends `i8` and `i16`
899/// values to `i32` before pushing them to the stack.
900pub fn push_wasm_ty_to_operand_stack<T>(value: T, stack: &mut Vec<RawFelt>)
901where
902    T: ToMidenRepr + num_traits::PrimInt,
903{
904    let ty_size = core::mem::size_of::<T>();
905    if ty_size > 2 {
906        value.push_to_operand_stack(stack);
907        return;
908    }
909
910    let is_signed = T::min_value() < T::zero();
911    // The unwraps below are safe because `value` is at most 16 bits wide.
912    let value_u32 = if is_signed {
913        value.to_i32().unwrap() as u32
914    } else {
915        value.to_u32().unwrap()
916    };
917    value_u32.push_to_operand_stack(stack);
918}
919
920#[cfg(test)]
921mod tests {
922    use alloc::vec::Vec;
923
924    use miden_core::Word;
925
926    use super::{FromMidenRepr, ToMidenRepr, bytes_to_words, push_wasm_ty_to_operand_stack};
927
928    #[test]
929    fn bool_roundtrip() {
930        let encoded = true.to_bytes();
931        let decoded = <bool as FromMidenRepr>::from_bytes(&encoded);
932        assert!(decoded);
933
934        let encoded = true.to_felts();
935        let decoded = <bool as FromMidenRepr>::from_felts(&encoded);
936        assert!(decoded);
937
938        let encoded = true.to_words();
939        let decoded = <bool as FromMidenRepr>::from_words(&encoded);
940        assert!(decoded);
941
942        let mut stack = Vec::default();
943        true.push_to_operand_stack(&mut stack);
944        assert_eq!(stack.as_slice(), true.to_felts().as_slice());
945
946        stack.reverse();
947        let popped = <bool as FromMidenRepr>::pop_from_stack(&mut stack);
948        assert!(popped);
949    }
950
951    #[test]
952    fn u8_roundtrip() {
953        let encoded = u8::MAX.to_bytes();
954        let decoded = <u8 as FromMidenRepr>::from_bytes(&encoded);
955        assert_eq!(decoded, u8::MAX);
956
957        let encoded = u8::MAX.to_felts();
958        let decoded = <u8 as FromMidenRepr>::from_felts(&encoded);
959        assert_eq!(decoded, u8::MAX);
960
961        let encoded = u8::MAX.to_words();
962        let decoded = <u8 as FromMidenRepr>::from_words(&encoded);
963        assert_eq!(decoded, u8::MAX);
964
965        let mut stack = Vec::default();
966        u8::MAX.push_to_operand_stack(&mut stack);
967        assert_eq!(stack.as_slice(), u8::MAX.to_felts().as_slice());
968
969        stack.reverse();
970        let popped = <u8 as FromMidenRepr>::pop_from_stack(&mut stack);
971        assert_eq!(popped, u8::MAX);
972    }
973
974    #[test]
975    fn u16_roundtrip() {
976        let encoded = u16::MAX.to_bytes();
977        let decoded = <u16 as FromMidenRepr>::from_bytes(&encoded);
978        assert_eq!(decoded, u16::MAX);
979
980        let encoded = u16::MAX.to_felts();
981        let decoded = <u16 as FromMidenRepr>::from_felts(&encoded);
982        assert_eq!(decoded, u16::MAX);
983
984        let encoded = u16::MAX.to_words();
985        let decoded = <u16 as FromMidenRepr>::from_words(&encoded);
986        assert_eq!(decoded, u16::MAX);
987
988        let mut stack = Vec::default();
989        u16::MAX.push_to_operand_stack(&mut stack);
990        assert_eq!(stack.as_slice(), u16::MAX.to_felts().as_slice());
991
992        stack.reverse();
993        let popped = <u16 as FromMidenRepr>::pop_from_stack(&mut stack);
994        assert_eq!(popped, u16::MAX);
995    }
996
997    #[test]
998    fn u32_roundtrip() {
999        let encoded = u32::MAX.to_bytes();
1000        let decoded = <u32 as FromMidenRepr>::from_bytes(&encoded);
1001        assert_eq!(decoded, u32::MAX);
1002
1003        let encoded = u32::MAX.to_felts();
1004        let decoded = <u32 as FromMidenRepr>::from_felts(&encoded);
1005        assert_eq!(decoded, u32::MAX);
1006
1007        let encoded = u32::MAX.to_words();
1008        let decoded = <u32 as FromMidenRepr>::from_words(&encoded);
1009        assert_eq!(decoded, u32::MAX);
1010
1011        let mut stack = Vec::default();
1012        u32::MAX.push_to_operand_stack(&mut stack);
1013        assert_eq!(stack.as_slice(), u32::MAX.to_felts().as_slice());
1014
1015        stack.reverse();
1016        let popped = <u32 as FromMidenRepr>::pop_from_stack(&mut stack);
1017        assert_eq!(popped, u32::MAX);
1018    }
1019
1020    #[test]
1021    fn u64_roundtrip() {
1022        let encoded = u64::MAX.to_bytes();
1023        let decoded = <u64 as FromMidenRepr>::from_bytes(&encoded);
1024        assert_eq!(decoded, u64::MAX);
1025
1026        let encoded = u64::MAX.to_felts();
1027        let decoded = <u64 as FromMidenRepr>::from_felts(&encoded);
1028        assert_eq!(decoded, u64::MAX);
1029
1030        let encoded = u64::MAX.to_words();
1031        let decoded = <u64 as FromMidenRepr>::from_words(&encoded);
1032        assert_eq!(decoded, u64::MAX);
1033
1034        let mut stack = Vec::default();
1035        u64::MAX.push_to_operand_stack(&mut stack);
1036        assert_eq!(stack.as_slice(), u64::MAX.to_felts().as_slice());
1037
1038        stack.reverse();
1039        let popped = <u64 as FromMidenRepr>::pop_from_stack(&mut stack);
1040        assert_eq!(popped, u64::MAX);
1041    }
1042
1043    #[test]
1044    fn u128_roundtrip() {
1045        let encoded = u128::MAX.to_bytes();
1046        let decoded = <u128 as FromMidenRepr>::from_bytes(&encoded);
1047        assert_eq!(decoded, u128::MAX);
1048
1049        let encoded = u128::MAX.to_felts();
1050        let decoded = <u128 as FromMidenRepr>::from_felts(&encoded);
1051        assert_eq!(decoded, u128::MAX);
1052
1053        let encoded = u128::MAX.to_words();
1054        let decoded = <u128 as FromMidenRepr>::from_words(&encoded);
1055        assert_eq!(decoded, u128::MAX);
1056
1057        let mut stack = Vec::default();
1058        u128::MAX.push_to_operand_stack(&mut stack);
1059        assert_eq!(stack.as_slice(), u128::MAX.to_felts().as_slice());
1060
1061        stack.reverse();
1062        let popped = <u128 as FromMidenRepr>::pop_from_stack(&mut stack);
1063        assert_eq!(popped, u128::MAX);
1064    }
1065
1066    #[test]
1067    fn byte_array_roundtrip() {
1068        let bytes = [0, 1, 2, 3, 4, 5, 6, 7];
1069
1070        let encoded = bytes.to_felts();
1071        let decoded = <[u8; 8] as FromMidenRepr>::from_felts(&encoded);
1072        assert_eq!(decoded, bytes);
1073
1074        let encoded = bytes.to_words();
1075        let decoded = <[u8; 8] as FromMidenRepr>::from_words(&encoded);
1076        assert_eq!(decoded, bytes);
1077
1078        let mut stack = Vec::default();
1079        bytes.push_to_operand_stack(&mut stack);
1080        assert_eq!(stack.as_slice(), bytes.to_felts().as_slice());
1081
1082        stack.reverse();
1083        let popped = <[u8; 8] as FromMidenRepr>::pop_from_stack(&mut stack);
1084        assert_eq!(popped, bytes);
1085    }
1086
1087    #[test]
1088    fn bytes_to_words_test() {
1089        let bytes = [
1090            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1091            25, 26, 27, 28, 29, 30, 31, 32,
1092        ];
1093        let words = bytes_to_words(&bytes);
1094        assert_eq!(words.len(), 2);
1095        // Words should be in little-endian order, elements of the word should be in big-endian
1096        assert_eq!(words[0][3].as_canonical_u64() as u32, u32::from_ne_bytes([1, 2, 3, 4]));
1097        assert_eq!(words[0][2].as_canonical_u64() as u32, u32::from_ne_bytes([5, 6, 7, 8]));
1098        assert_eq!(words[0][1].as_canonical_u64() as u32, u32::from_ne_bytes([9, 10, 11, 12]));
1099        assert_eq!(words[0][0].as_canonical_u64() as u32, u32::from_ne_bytes([13, 14, 15, 16]));
1100
1101        // Make sure bytes_to_words and to_words agree
1102        let to_words_output = bytes.to_words();
1103        assert_eq!(Word::new(words[0]), to_words_output[0]);
1104    }
1105
1106    #[test]
1107    fn bytes_from_words_test() {
1108        let bytes = [
1109            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1110            25, 26, 27, 28, 29, 30, 31, 32,
1111        ];
1112        let words_as_bytes = bytes_to_words(&bytes);
1113
1114        let words = vec![Word::new(words_as_bytes[0]), Word::new(words_as_bytes[1])];
1115
1116        let out = <[u8; 32] as FromMidenRepr>::from_words(&words);
1117
1118        assert_eq!(&out, &bytes);
1119    }
1120
1121    #[test]
1122    fn push_wasm_ty_to_operand_stack_test() {
1123        let mut stack = Vec::default();
1124        push_wasm_ty_to_operand_stack(i8::MIN, &mut stack);
1125        push_wasm_ty_to_operand_stack(i16::MIN, &mut stack);
1126        push_wasm_ty_to_operand_stack(u32::MAX, &mut stack);
1127
1128        assert_eq!(stack[0].as_canonical_u64(), ((i8::MIN as i32) as u32) as u64);
1129        assert_eq!(stack[1].as_canonical_u64(), ((i16::MIN as i32) as u32) as u64);
1130        assert_eq!(stack[2].as_canonical_u64(), u32::MAX as u64);
1131    }
1132}