Skip to main content

miden_debug/
felt.rs

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