Skip to main content

miden_debug_engine/
felt.rs

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