Skip to main content

miden_debug_engine/
felt.rs

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