1use std::borrow::Cow;
2use std::error::Error;
3use std::str::FromStr;
4
5use bitvec::order::Msb0;
6use bitvec::slice::BitSlice;
7use bitvec::view::BitView;
8use fake::Dummy;
9use num_bigint::{BigUint, ParseBigIntError};
10
11use crate::algebra::field::montfelt::MontFelt;
12
13#[derive(Clone, Copy, PartialEq, Hash, Eq, PartialOrd, Ord)]
18pub struct Felt([u8; 32]);
19
20const MODULUS_U64: [u64; 4] = [576460752303423505u64, 0, 0, 1];
21
22impl std::fmt::Debug for Felt {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 write!(f, "Felt({self})")
25 }
26}
27
28impl std::fmt::Display for Felt {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 write!(f, "0x{self:X}")
32 }
33}
34
35impl std::fmt::LowerHex for Felt {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 self.0.iter().try_for_each(|&b| write!(f, "{b:02x}"))
38 }
39}
40
41impl std::fmt::UpperHex for Felt {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 self.0.iter().try_for_each(|&b| write!(f, "{b:02X}"))
44 }
45}
46
47impl Default for Felt {
48 fn default() -> Self {
49 Felt::ZERO
50 }
51}
52
53impl<T> Dummy<T> for Felt {
54 fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &T, rng: &mut R) -> Self {
55 let mut bytes = [0u8; 32];
56 rng.fill_bytes(&mut bytes);
57 bytes[0] &= 0x03;
59 Self(bytes)
60 }
61}
62
63#[derive(Debug, PartialEq, Eq, Clone, Copy)]
66pub struct OverflowError;
67
68impl Error for OverflowError {}
69
70const OVERFLOW_MSG: &str = "The maximum field value was exceeded.";
71
72impl std::fmt::Display for OverflowError {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 f.write_str(OVERFLOW_MSG)
75 }
76}
77
78impl Felt {
79 pub const ZERO: Felt = Felt([0u8; 32]);
80 pub const ONE: Felt = Self::from_u64(1);
81
82 pub fn is_zero(&self) -> bool {
84 self == &Felt::ZERO
85 }
86
87 pub const fn to_be_bytes(self) -> [u8; 32] {
89 self.0
90 }
91
92 pub fn to_le_bytes(self) -> [u8; 32] {
94 let mut tmp = self.0;
95 tmp.reverse();
96 tmp
97 }
98
99 pub const fn as_be_bytes(&self) -> &[u8; 32] {
101 &self.0
102 }
103
104 pub fn as_mut_be_bytes(&mut self) -> &mut [u8; 32] {
106 &mut self.0
107 }
108
109 pub const fn from_be_slice(bytes: &[u8]) -> Result<Self, OverflowError> {
112 if bytes.len() > 32 {
113 return Err(OverflowError);
114 }
115
116 let mut buf = [0u8; 32];
117 let mut index = 0;
118 loop {
119 if index == bytes.len() {
120 break;
121 }
122 buf[32 - bytes.len() + index] = bytes[index];
123 index += 1;
124 }
125
126 Felt::from_be_bytes(buf)
127 }
128
129 pub fn random<R: rand::Rng>(rng: &mut R) -> Self {
130 let r = MontFelt::random(rng);
131 Felt::from(r)
132 }
133
134 pub const fn from_be_bytes(bytes: [u8; 32]) -> Result<Self, OverflowError> {
138 #[rustfmt::skip]
139 let limbs = [
140 u64::from_be_bytes([
141 bytes[0], bytes[1], bytes[2], bytes[3],
142 bytes[4], bytes[5], bytes[6], bytes[7],
143 ]),
144 u64::from_be_bytes([
145 bytes[8], bytes[9], bytes[10], bytes[11],
146 bytes[12], bytes[13], bytes[14], bytes[15],
147 ]),
148 u64::from_be_bytes([
149 bytes[16], bytes[17], bytes[18], bytes[19],
150 bytes[20], bytes[21], bytes[22], bytes[23],
151 ]),
152 u64::from_be_bytes([
153 bytes[24], bytes[25], bytes[26], bytes[27],
154 bytes[28], bytes[29], bytes[30], bytes[31],
155 ]),
156 ];
157
158 let mut maybe_overflow = true;
161 let mut i = 0;
162 while i < 4 && maybe_overflow {
163 if limbs[i] < MODULUS_U64[i] {
164 maybe_overflow = false;
165 } else if limbs[i] > MODULUS_U64[i] {
166 return Err(OverflowError);
167 }
168 i += 1;
169 }
170 if maybe_overflow {
171 Err(OverflowError)
172 } else {
173 Ok(Felt(bytes))
174 }
175 }
176
177 pub fn view_bits(&self) -> &BitSlice<u8, Msb0> {
179 &self.0.view_bits()[5..]
180 }
181
182 pub fn from_bits(bits: &BitSlice<u8, Msb0>) -> Result<Self, OverflowError> {
184 if bits.len() > 251 {
185 return Err(OverflowError);
186 }
187
188 let mut bytes = [0u8; 32];
189 bytes.view_bits_mut::<Msb0>()[256 - bits.len()..].copy_from_bitslice(bits);
190
191 Ok(Self(bytes))
192 }
193
194 pub const fn has_more_than_251_bits(&self) -> bool {
199 self.0[0] & 0b1111_1000 > 0
200 }
201
202 pub const fn from_u64(u: u64) -> Self {
203 const_expect!(
204 Self::from_be_slice(&u.to_be_bytes()),
205 "64 bits is less than 251 bits"
206 )
207 }
208
209 pub const fn from_u128(u: u128) -> Self {
210 const_expect!(
211 Self::from_be_slice(&u.to_be_bytes()),
212 "128 bits is less than 251 bits"
213 )
214 }
215}
216
217macro_rules! const_expect {
218 ($e:expr, $why:expr) => {{
219 match $e {
220 Ok(x) => x,
221 Err(_) => panic!(concat!("Expectation failed: ", $why)),
222 }
223 }};
224}
225
226use const_expect;
227
228use crate::algebra::field::CurveOrderMontFelt;
229
230impl From<u64> for Felt {
231 fn from(value: u64) -> Self {
232 Self::from_u64(value)
233 }
234}
235
236impl From<usize> for Felt {
237 fn from(value: usize) -> Self {
238 Self::from_u64(value.try_into().expect("ptr size is 64 bits"))
239 }
240}
241
242impl From<u128> for Felt {
243 fn from(value: u128) -> Self {
244 Self::from_u128(value)
245 }
246}
247
248impl From<[u8; 32]> for Felt {
249 fn from(bytes: [u8; 32]) -> Self {
250 Self(bytes)
251 }
252}
253
254impl TryInto<u128> for Felt {
255 type Error = OverflowError;
256
257 fn try_into(self) -> Result<u128, Self::Error> {
258 let initial_zeroes = self.0.iter().take_while(|b| **b == 0).count();
259 const EXPECTED_ZEROES: usize = (32 - u128::BITS / u8::BITS) as usize;
260
261 if initial_zeroes < EXPECTED_ZEROES {
262 return Err(OverflowError);
263 }
264
265 let bytes = self.0[EXPECTED_ZEROES..]
266 .try_into()
267 .expect("Should match u128 size");
268 Ok(u128::from_be_bytes(bytes))
269 }
270}
271
272impl TryInto<u64> for Felt {
273 type Error = OverflowError;
274
275 fn try_into(self) -> Result<u64, Self::Error> {
276 let initial_zeroes = self.0.iter().take_while(|b| **b == 0).count();
277 const EXPECTED_ZEROES: usize = (32 - u64::BITS / u8::BITS) as usize;
278
279 if initial_zeroes < EXPECTED_ZEROES {
280 return Err(OverflowError);
281 }
282 let bytes = self.0[EXPECTED_ZEROES..]
283 .try_into()
284 .expect("Should match u64 size");
285 Ok(u64::from_be_bytes(bytes))
286 }
287}
288
289impl std::ops::Add for Felt {
290 type Output = Felt;
291
292 fn add(self, rhs: Self) -> Self::Output {
293 let result = MontFelt::from(self) + MontFelt::from(rhs);
294 Felt::from(result)
295 }
296}
297
298impl std::ops::Sub for Felt {
299 type Output = Felt;
300
301 fn sub(self, rhs: Self) -> Self::Output {
302 let result = MontFelt::from(self) - MontFelt::from(rhs);
303 Felt::from(result)
304 }
305}
306
307impl From<MontFelt> for Felt {
308 fn from(fp: MontFelt) -> Self {
309 debug_assert_eq!(std::mem::size_of::<MontFelt>(), std::mem::size_of::<Felt>());
311 let bytes: [u8; 32] = fp.to_be_bytes();
312 Felt::from_be_bytes(bytes).unwrap()
313 }
314}
315
316impl From<CurveOrderMontFelt> for Felt {
317 fn from(value: CurveOrderMontFelt) -> Self {
318 debug_assert_eq!(std::mem::size_of::<MontFelt>(), std::mem::size_of::<Felt>());
320 let bytes = value.to_be_bytes();
321 Felt::from_be_bytes(bytes).unwrap()
322 }
323}
324
325impl Felt {
326 pub const fn from_hex_str(hex_str: &str) -> Result<Self, HexParseError> {
331 const fn parse_hex_digit(digit: u8) -> Result<u8, HexParseError> {
332 match digit {
333 b'0'..=b'9' => Ok(digit - b'0'),
334 b'A'..=b'F' => Ok(digit - b'A' + 10),
335 b'a'..=b'f' => Ok(digit - b'a' + 10),
336 other => Err(HexParseError::InvalidNibble(other)),
337 }
338 }
339
340 let bytes = hex_str.as_bytes();
341 let len = match bytes {
342 [b'0', b'x', rest @ ..] if rest.len() > 64 => {
343 return Err(HexParseError::InvalidLength {
344 max: 64,
345 actual: rest.len(),
346 })
347 }
348 [b'0', b'x', rest @ ..] => rest.len(),
349 _ => return Err(HexParseError::MissingPrefix),
350 };
351
352 let mut buf = [0u8; 32];
353
354 if len % 2 == 1 {
359 let idx = len / 2;
360 buf[31 - idx] = match parse_hex_digit(bytes[2]) {
361 Ok(b) => b,
362 Err(e) => return Err(e),
363 };
364 }
365
366 let chunks = len / 2;
367 let mut chunk = 0;
368
369 while chunk < chunks {
370 let lower = match parse_hex_digit(bytes[bytes.len() - chunk * 2 - 1]) {
371 Ok(b) => b,
372 Err(e) => return Err(e),
373 };
374 let upper = match parse_hex_digit(bytes[bytes.len() - chunk * 2 - 2]) {
375 Ok(b) => b,
376 Err(e) => return Err(e),
377 };
378 buf[31 - chunk] = (upper << 4) | lower;
379 chunk += 1;
380 }
381
382 let felt = match Felt::from_be_bytes(buf) {
383 Ok(felt) => felt,
384 Err(OverflowError) => return Err(HexParseError::Overflow),
385 };
386 Ok(felt)
387 }
388
389 fn skip_zeros(&self) -> (impl Iterator<Item = &u8>, usize, usize) {
391 let it = self.0.iter().skip_while(|&&b| b == 0);
393 let num_bytes = it.clone().count();
394 let skipped = self.0.len() - num_bytes;
395 let start = if self.0[skipped] < 0x10 { 1 } else { 2 };
397 let len = start + num_bytes * 2;
399 (it, start, len)
400 }
401
402 fn it_to_hex_str<'a>(
404 it: impl Iterator<Item = &'a u8>,
405 start: usize,
406 len: usize,
407 buf: &'a mut [u8],
408 ) -> &'a [u8] {
409 const LUT: [u8; 16] = *b"0123456789abcdef";
410 buf[0] = b'0';
411 it.enumerate().for_each(|(i, &b)| {
413 let idx = b as usize;
414 let pos = start + i * 2;
415 let x = [LUT[(idx & 0xf0) >> 4], LUT[idx & 0x0f]];
416 buf[pos..pos + 2].copy_from_slice(&x);
417 });
418 buf[1] = b'x';
419 &buf[..len]
420 }
421
422 pub fn as_hex_str<'a>(&'a self, buf: &'a mut [u8]) -> &'a str {
426 let expected_buf_len = self.0.len() * 2 + 2;
427 assert!(
428 buf.len() >= expected_buf_len,
429 "buffer size is {}, expected at least {}",
430 buf.len(),
431 expected_buf_len
432 );
433
434 if !self.0.iter().any(|b| *b != 0) {
435 return "0x0";
436 }
437
438 let (it, start, len) = self.skip_zeros();
439 let res = Self::it_to_hex_str(it, start, len, buf);
440 std::str::from_utf8(res).unwrap()
442 }
443
444 pub fn to_hex_str(&self) -> Cow<'static, str> {
447 if !self.0.iter().any(|b| *b != 0) {
448 return Cow::from("0x0");
449 }
450 let (it, start, len) = self.skip_zeros();
451 let mut buf = vec![0u8; len];
452 Self::it_to_hex_str(it, start, len, &mut buf);
453 String::from_utf8(buf).unwrap().into()
455 }
456
457 pub fn from_biguint(b: BigUint) -> Result<Self, OverflowError> {
462 Self::from_be_slice(&b.to_bytes_be())
463 }
464
465 pub fn from_dec_str(s: &str) -> Result<Self, DecParseError> {
470 match Felt::from_hex_str(s) {
473 Ok(h) => Ok(h),
474 Err(_) => {
475 let b = BigUint::from_str(s)?;
476 let h = Self::from_biguint(b)?;
477 Ok(h)
478 }
479 }
480 }
481
482 pub fn to_dec_str(&self) -> String {
487 let b = self.to_be_bytes();
488 let b = BigUint::from_bytes_be(&b);
489 b.to_str_radix(10)
490 }
491}
492
493#[derive(Debug, PartialEq, Eq)]
495pub enum HexParseError {
496 InvalidNibble(u8),
497 InvalidLength { max: usize, actual: usize },
498 MissingPrefix,
499 Overflow,
500}
501
502impl Error for HexParseError {}
503
504impl From<OverflowError> for HexParseError {
505 fn from(_: OverflowError) -> Self {
506 Self::Overflow
507 }
508}
509
510impl std::fmt::Display for HexParseError {
511 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
512 match self {
513 Self::InvalidNibble(n) => f.write_fmt(format_args!("Invalid nibble found: 0x{:x}", *n)),
514 Self::InvalidLength { max, actual } => {
515 f.write_fmt(format_args!("More than {} digits found: {}", *max, *actual))
516 }
517 Self::MissingPrefix => f.write_str("Missing '0x' prefix"),
518 Self::Overflow => f.write_str(OVERFLOW_MSG),
519 }
520 }
521}
522
523#[derive(Debug)]
526pub enum DecParseError {
527 ParseBigInt(ParseBigIntError),
528 Overflow,
529}
530
531impl Error for DecParseError {}
532
533impl From<ParseBigIntError> for DecParseError {
534 fn from(e: ParseBigIntError) -> Self {
535 Self::ParseBigInt(e)
536 }
537}
538
539impl From<OverflowError> for DecParseError {
540 fn from(_: OverflowError) -> Self {
541 Self::Overflow
542 }
543}
544
545impl std::fmt::Display for DecParseError {
546 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
547 match self {
548 Self::ParseBigInt(e) => {
549 f.write_fmt(format_args!("Failed to parse decimal string: {e}"))
550 }
551 Self::Overflow => f.write_str(OVERFLOW_MSG),
552 }
553 }
554}
555
556#[cfg(test)]
557mod tests {
558 use bitvec::bitvec;
559 use pretty_assertions_sorted::assert_eq;
560
561 use super::*;
562
563 const MODULUS_U8: [u8; 32] = [
564 8, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
565 0, 1,
566 ];
567
568 #[test]
569 fn view_bits() {
570 let one = Felt::from_hex_str("0x1").unwrap();
571
572 let one = one.view_bits().to_bitvec();
573
574 let mut expected = bitvec![0; 251];
575 expected.set(250, true);
576 assert_eq!(one, expected);
577 }
578
579 #[test]
580 fn bits_round_trip() {
581 let mut bits = bitvec![u8, Msb0; 1; 251];
582 bits.set(0, false);
583 bits.set(1, false);
584 bits.set(2, false);
585 bits.set(3, false);
586 bits.set(4, false);
587
588 let res = Felt::from_bits(&bits).unwrap();
589
590 let x = res.view_bits();
591 let y = Felt::from_bits(x).unwrap();
592
593 assert_eq!(res, y);
594 }
595
596 #[test]
597 fn bytes_round_trip() {
598 let original = [
599 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
600 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
601 0x1C, 0x1D, 0x1E, 0x1F,
602 ];
603 let hash = Felt::from_be_bytes(original).unwrap();
604 let bytes = hash.to_be_bytes();
605 assert_eq!(bytes, original);
606 }
607
608 #[test]
609 fn from_bytes_overflow() {
610 assert_eq!(Felt::from_be_bytes(MODULUS_U8), Err(OverflowError));
612 let mut max_val = MODULUS_U8;
614 max_val[31] -= 1;
615 Felt::from_be_bytes(max_val).unwrap();
616 }
617
618 #[test]
619 fn field_round_trip() {
620 let bytes = [
621 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
622 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
623 0x1C, 0x1D, 0x1E, 0x1F,
624 ];
625 let original = Felt::from_be_bytes(bytes).unwrap();
626 let fp = MontFelt::from(original);
627 let hash = Felt::from(fp);
628 assert_eq!(hash, original);
629 }
630
631 mod from_be_slice {
632 use pretty_assertions_sorted::assert_eq;
633
634 use super::*;
635
636 #[test]
637 fn round_trip() {
638 let original = Felt::from_hex_str("0xabcdef0123456789").unwrap();
639 let bytes = original.to_be_bytes();
640 let result = Felt::from_be_slice(&bytes[..]).unwrap();
641
642 assert_eq!(result, original);
643 }
644
645 #[test]
646 fn too_long() {
647 let original = Felt::from_hex_str("0xabcdef0123456789").unwrap();
648 let mut bytes = original.to_be_bytes().to_vec();
649 bytes.push(0);
650 Felt::from_be_slice(&bytes[..]).unwrap_err();
651 }
652
653 #[test]
654 fn short_slice() {
655 let original = Felt::from_hex_str("0xabcdef0123456789").unwrap();
656 let bytes = original.to_be_bytes();
657 let result = Felt::from_be_slice(&bytes[24..]);
658
659 assert_eq!(result, Ok(original));
660 }
661
662 #[test]
663 fn max() {
664 let mut max_val = MODULUS_U8;
665 max_val[31] -= 1;
666 Felt::from_be_slice(&max_val[..]).unwrap();
667 }
668
669 #[test]
670 fn overflow() {
671 assert_eq!(Felt::from_be_slice(&MODULUS_U8[..]), Err(OverflowError));
672 }
673 }
674
675 mod fmt {
676 use pretty_assertions_sorted::assert_eq;
677
678 use super::Felt;
679
680 #[test]
681 fn debug() {
682 let hex_str = "0x1234567890abcdef000edcba0987654321";
683 let felt = Felt::from_hex_str(hex_str).unwrap();
684 let result = format!("{felt:?}");
685
686 let leading_zeros = "0".repeat(64 + 2 - hex_str.len());
687 let hex_upper_stripped = hex_str.strip_prefix("0x").unwrap().to_uppercase();
688 let expected = format!("Felt(0x{leading_zeros}{hex_upper_stripped})");
689
690 assert_eq!(result, expected);
691 }
692
693 #[test]
694 fn fmt() {
695 let hex_str = "0x1234567890abcdef000edcba0987654321";
696 let starkhash = Felt::from_hex_str(hex_str).unwrap();
697 let result = format!("{starkhash:x}");
698
699 let mut expected = "0".repeat(64 - hex_str.len() + 2);
700 expected.push_str(&hex_str[2..]);
701
702 assert_eq!(result.to_lowercase(), expected.to_lowercase());
704 }
705
706 #[test]
707 fn lower_hex() {
708 let hex_str = "0x1234567890abcdef000edcba0987654321";
709 let starkhash = Felt::from_hex_str(hex_str).unwrap();
710 let result = format!("{starkhash:x}");
711
712 let mut expected = "0".repeat(64 - hex_str.len() + 2);
713 expected.push_str(&hex_str[2..]);
714
715 assert_eq!(result, expected.to_lowercase());
716 }
717
718 #[test]
719 fn upper_hex() {
720 let hex_str = "0x1234567890abcdef000edcba0987654321";
721 let starkhash = Felt::from_hex_str(hex_str).unwrap();
722 let result = format!("{starkhash:X}");
723
724 let mut expected = "0".repeat(64 - hex_str.len() + 2);
725 expected.push_str(&hex_str[2..]);
726
727 assert_eq!(result, expected.to_uppercase());
728 }
729 }
730
731 mod from_hex_str {
732 use assert_matches::assert_matches;
733 use pretty_assertions_sorted::assert_eq;
734
735 use super::*;
736
737 fn test_data() -> (&'static str, Felt) {
739 let mut expected = [0; 32];
740 expected[31] = 0xEF;
741 expected[30] = 0xCD;
742 expected[29] = 0xAB;
743 expected[28] = 0xef;
744 expected[27] = 0xcd;
745 expected[26] = 0xab;
746 expected[25] = 0x89;
747 expected[24] = 0x67;
748 expected[23] = 0x45;
749 expected[22] = 0x23;
750 expected[21] = 0x01;
751 let expected = Felt::from_be_bytes(expected).unwrap();
752
753 ("0123456789abcdefABCDEF", expected)
754 }
755
756 #[test]
757 fn simple() {
758 let (test_str, expected) = test_data();
759 let uut = Felt::from_hex_str(&format!("0x{test_str}")).unwrap();
760 assert_eq!(uut, expected);
761 }
762
763 #[test]
764 fn leading_zeros() {
765 let (test_str, expected) = test_data();
766 let uut = Felt::from_hex_str(&format!("0x000000000{test_str}")).unwrap();
767 assert_eq!(uut, expected);
768 }
769
770 #[test]
771 fn invalid_nibble() {
772 assert_matches!(Felt::from_hex_str("0x123z").unwrap_err(), HexParseError::InvalidNibble(n) => assert_eq!(n, b'z'))
773 }
774
775 #[test]
776 fn missing_prefix() {
777 assert_matches!(
778 Felt::from_hex_str("123").unwrap_err(),
779 HexParseError::MissingPrefix
780 )
781 }
782
783 #[test]
784 fn invalid_len() {
785 let invalid_str = "0".repeat(65);
786 assert_matches!(
787 Felt::from_hex_str(&format!("0x{invalid_str}")).unwrap_err(),
788 HexParseError::InvalidLength {
789 max: 64,
790 actual: 65
791 }
792 );
793 }
794
795 #[test]
796 fn overflow() {
797 let mut modulus =
799 "0x800000000000011000000000000000000000000000000000000000000000001".to_string();
800 assert_eq!(
801 Felt::from_hex_str(&modulus).unwrap_err(),
802 HexParseError::Overflow
803 );
804 modulus.pop();
806 modulus.push('0');
807 Felt::from_hex_str(&modulus).unwrap();
808 }
809 }
810
811 mod to_hex_str {
812 use pretty_assertions_sorted::assert_eq;
813
814 use super::*;
815
816 const ODD: &str = "0x1234567890abcde";
817 const EVEN: &str = "0x1234567890abcdef";
818 const MAX: &str = "0x800000000000011000000000000000000000000000000000000000000000000";
819
820 #[test]
821 fn zero() {
822 assert_eq!(Felt::ZERO.to_hex_str(), "0x0");
823 let mut buf = [0u8; 66];
824 assert_eq!(Felt::ZERO.as_hex_str(&mut buf), "0x0");
825 }
826
827 #[test]
828 fn odd() {
829 let hash = Felt::from_hex_str(ODD).unwrap();
830 assert_eq!(hash.to_hex_str(), ODD);
831 let mut buf = [0u8; 66];
832 assert_eq!(hash.as_hex_str(&mut buf), ODD);
833 }
834
835 #[test]
836 fn even() {
837 let hash = Felt::from_hex_str(EVEN).unwrap();
838 assert_eq!(hash.to_hex_str(), EVEN);
839 let mut buf = [0u8; 66];
840 assert_eq!(hash.as_hex_str(&mut buf), EVEN);
841 }
842
843 #[test]
844 fn max() {
845 let hash = Felt::from_hex_str(MAX).unwrap();
846 assert_eq!(hash.to_hex_str(), MAX);
847 let mut buf = [0u8; 66];
848 assert_eq!(hash.as_hex_str(&mut buf), MAX);
849 }
850
851 #[test]
852 #[should_panic]
853 fn buffer_too_small() {
854 let mut buf = [0u8; 65];
855 Felt::ZERO.as_hex_str(&mut buf);
856 }
857 }
858
859 mod has_more_than_251_bits {
860 use super::*;
861
862 #[test]
863 fn has_251_bits() {
864 let mut bytes = [0xFFu8; 32];
865 bytes[0] = 0x07;
866 let h = Felt::from_be_bytes(bytes).unwrap();
867 assert!(!h.has_more_than_251_bits());
868 }
869
870 #[test]
871 fn has_252_bits() {
872 let mut bytes = [0u8; 32];
873 bytes[0] = 0x08;
874 let h = Felt::from_be_bytes(bytes).unwrap();
875 assert!(h.has_more_than_251_bits());
876 }
877 }
878}