Skip to main content

miden_debug/
felt.rs

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