1use alloc::{boxed::Box, fmt::Formatter, format, string::*, vec::*};
2use core::{fmt::Display, mem::MaybeUninit};
3use starknet_rust_crypto::{Blake2Hasher, PedersenHasher, PoseidonHasher};
4
5use num_traits::ToPrimitive;
6
7use crate::types::{Felt, U256};
8
9pub use starknet_rust_core_derive::{Decode, Encode};
10
11const I128_MIN: Felt =
12 Felt::from_hex_unchecked("0x0800000000000010ffffffffffffffff80000000000000000000000000000001");
13const I128_MAX: Felt =
14 Felt::from_hex_unchecked("0x000000000000000000000000000000007fffffffffffffffffffffffffffffff");
15
16pub trait FeltWriter {
23 fn write(&mut self, felt: Felt);
25}
26
27pub trait Encode {
58 fn encode<W: FeltWriter>(&self, writer: &mut W) -> Result<(), Error>;
60}
61
62pub trait Decode<'a>: Sized {
92 fn decode<T>(reader: T) -> Result<Self, Error>
94 where
95 T: IntoIterator<Item = &'a Felt>,
96 {
97 Self::decode_iter(&mut reader.into_iter())
98 }
99
100 fn decode_iter<T>(iter: &mut T) -> Result<Self, Error>
102 where
103 T: Iterator<Item = &'a Felt>;
104}
105
106#[derive(Debug)]
117pub struct Error {
118 repr: Box<str>,
119}
120
121impl FeltWriter for Felt {
123 fn write(&mut self, felt: Felt) {
124 *self = felt;
125 }
126}
127
128impl FeltWriter for Vec<Felt> {
129 fn write(&mut self, felt: Felt) {
130 self.push(felt);
131 }
132}
133
134impl FeltWriter for PedersenHasher {
135 fn write(&mut self, felt: Felt) {
136 self.update(felt);
137 }
138}
139
140impl FeltWriter for PoseidonHasher {
141 fn write(&mut self, felt: Felt) {
142 self.update(felt);
143 }
144}
145
146impl FeltWriter for Blake2Hasher {
147 fn write(&mut self, felt: Felt) {
148 self.update(felt);
149 }
150}
151
152impl Encode for Felt {
153 fn encode<W: FeltWriter>(&self, writer: &mut W) -> Result<(), Error> {
154 writer.write(*self);
155 Ok(())
156 }
157}
158
159impl Encode for bool {
160 fn encode<W: FeltWriter>(&self, writer: &mut W) -> Result<(), Error> {
161 writer.write(if *self { Felt::ONE } else { Felt::ZERO });
162 Ok(())
163 }
164}
165
166impl Encode for u8 {
167 fn encode<W: FeltWriter>(&self, writer: &mut W) -> Result<(), Error> {
168 writer.write((*self).into());
169 Ok(())
170 }
171}
172
173impl Encode for u16 {
174 fn encode<W: FeltWriter>(&self, writer: &mut W) -> Result<(), Error> {
175 writer.write((*self).into());
176 Ok(())
177 }
178}
179
180impl Encode for u32 {
181 fn encode<W: FeltWriter>(&self, writer: &mut W) -> Result<(), Error> {
182 writer.write((*self).into());
183 Ok(())
184 }
185}
186
187impl Encode for u64 {
188 fn encode<W: FeltWriter>(&self, writer: &mut W) -> Result<(), Error> {
189 writer.write((*self).into());
190 Ok(())
191 }
192}
193
194impl Encode for u128 {
195 fn encode<W: FeltWriter>(&self, writer: &mut W) -> Result<(), Error> {
196 writer.write((*self).into());
197 Ok(())
198 }
199}
200
201impl Encode for U256 {
202 fn encode<W: FeltWriter>(&self, writer: &mut W) -> Result<(), Error> {
203 self.low().encode(writer)?;
204 self.high().encode(writer)?;
205 Ok(())
206 }
207}
208
209impl Encode for i128 {
210 fn encode<W: FeltWriter>(&self, writer: &mut W) -> Result<(), Error> {
211 writer.write((*self).into());
212 Ok(())
213 }
214}
215
216impl<T> Encode for Option<T>
217where
218 T: Encode,
219{
220 fn encode<W: FeltWriter>(&self, writer: &mut W) -> Result<(), Error> {
221 match self {
222 Some(inner) => {
223 writer.write(Felt::ZERO);
224 inner.encode(writer)?;
225 }
226 None => {
227 writer.write(Felt::ONE);
228 }
229 }
230
231 Ok(())
232 }
233}
234
235impl<T> Encode for Vec<T>
236where
237 T: Encode,
238{
239 fn encode<W: FeltWriter>(&self, writer: &mut W) -> Result<(), Error> {
240 writer.write(Felt::from(self.len()));
241
242 for item in self {
243 item.encode(writer)?;
244 }
245
246 Ok(())
247 }
248}
249
250impl<T, const N: usize> Encode for [T; N]
251where
252 T: Encode,
253{
254 fn encode<W: FeltWriter>(&self, writer: &mut W) -> Result<(), Error> {
255 writer.write(Felt::from(N));
256
257 for item in self {
258 item.encode(writer)?;
259 }
260
261 Ok(())
262 }
263}
264
265impl<T> Encode for [T]
266where
267 T: Encode,
268{
269 fn encode<W: FeltWriter>(&self, writer: &mut W) -> Result<(), Error> {
270 writer.write(Felt::from(self.len()));
271
272 for item in self {
273 item.encode(writer)?;
274 }
275
276 Ok(())
277 }
278}
279
280impl<'a> Decode<'a> for Felt {
281 fn decode_iter<T>(iter: &mut T) -> Result<Self, Error>
282 where
283 T: Iterator<Item = &'a Self>,
284 {
285 iter.next().ok_or_else(Error::input_exhausted).cloned()
286 }
287}
288
289impl<'a> Decode<'a> for bool {
290 fn decode_iter<T>(iter: &mut T) -> Result<Self, Error>
291 where
292 T: Iterator<Item = &'a Felt>,
293 {
294 let input = iter.next().ok_or_else(Error::input_exhausted)?;
295 if input == &Felt::ZERO {
296 Ok(false)
297 } else if input == &Felt::ONE {
298 Ok(true)
299 } else {
300 Err(Error::value_out_of_range(input, "bool"))
301 }
302 }
303}
304
305impl<'a> Decode<'a> for u8 {
306 fn decode_iter<T>(iter: &mut T) -> Result<Self, Error>
307 where
308 T: Iterator<Item = &'a Felt>,
309 {
310 let input = iter.next().ok_or_else(Error::input_exhausted)?;
311 input
312 .to_u8()
313 .ok_or_else(|| Error::value_out_of_range(input, "u8"))
314 }
315}
316
317impl<'a> Decode<'a> for u16 {
318 fn decode_iter<T>(iter: &mut T) -> Result<Self, Error>
319 where
320 T: Iterator<Item = &'a Felt>,
321 {
322 let input = iter.next().ok_or_else(Error::input_exhausted)?;
323 input
324 .to_u16()
325 .ok_or_else(|| Error::value_out_of_range(input, "u16"))
326 }
327}
328
329impl<'a> Decode<'a> for u32 {
330 fn decode_iter<T>(iter: &mut T) -> Result<Self, Error>
331 where
332 T: Iterator<Item = &'a Felt>,
333 {
334 let input = iter.next().ok_or_else(Error::input_exhausted)?;
335 input
336 .to_u32()
337 .ok_or_else(|| Error::value_out_of_range(input, "u32"))
338 }
339}
340
341impl<'a> Decode<'a> for u64 {
342 fn decode_iter<T>(iter: &mut T) -> Result<Self, Error>
343 where
344 T: Iterator<Item = &'a Felt>,
345 {
346 let input = iter.into_iter().next().ok_or_else(Error::input_exhausted)?;
347 input
348 .to_u64()
349 .ok_or_else(|| Error::value_out_of_range(input, "u64"))
350 }
351}
352
353impl<'a> Decode<'a> for u128 {
354 fn decode_iter<T>(iter: &mut T) -> Result<Self, Error>
355 where
356 T: Iterator<Item = &'a Felt>,
357 {
358 let input = iter.next().ok_or_else(Error::input_exhausted)?;
359 input
360 .to_u128()
361 .ok_or_else(|| Error::value_out_of_range(input, "u128"))
362 }
363}
364
365impl<'a> Decode<'a> for U256 {
366 fn decode_iter<T>(iter: &mut T) -> Result<Self, Error>
367 where
368 T: Iterator<Item = &'a Felt>,
369 {
370 let input_low = iter.next().ok_or_else(Error::input_exhausted)?;
371 let input_high = iter.next().ok_or_else(Error::input_exhausted)?;
372
373 let input_low = input_low
374 .to_u128()
375 .ok_or_else(|| Error::value_out_of_range(input_low, "u128"))?;
376 let input_high = input_high
377 .to_u128()
378 .ok_or_else(|| Error::value_out_of_range(input_high, "u128"))?;
379
380 Ok(Self::from_words(input_low, input_high))
381 }
382}
383
384impl<'a> Decode<'a> for i128 {
385 fn decode_iter<T>(iter: &mut T) -> Result<Self, Error>
386 where
387 T: Iterator<Item = &'a Felt>,
388 {
389 let input = iter.next().ok_or_else(Error::input_exhausted)?;
390
391 if input <= &I128_MAX {
392 Ok(input.to_i128().unwrap())
394 } else if input >= &I128_MIN {
395 Ok(Self::MIN + (input - I128_MIN).to_i128().unwrap())
397 } else {
398 Err(Error::value_out_of_range(input, "i128"))
399 }
400 }
401}
402
403impl<'a, T> Decode<'a> for Option<T>
404where
405 T: Decode<'a>,
406{
407 fn decode_iter<I>(iter: &mut I) -> Result<Self, Error>
408 where
409 I: Iterator<Item = &'a Felt>,
410 {
411 let tag = iter.next().ok_or_else(Error::input_exhausted)?;
412
413 if tag == &Felt::ZERO {
414 Ok(Some(T::decode_iter(iter)?))
415 } else if tag == &Felt::ONE {
416 Ok(None)
417 } else {
418 Err(Error::unknown_enum_tag(tag, "Option<T>"))
419 }
420 }
421}
422
423impl<'a, T> Decode<'a> for Vec<T>
424where
425 T: Decode<'a>,
426{
427 fn decode_iter<I>(iter: &mut I) -> Result<Self, Error>
428 where
429 I: Iterator<Item = &'a Felt>,
430 {
431 let length = iter.next().ok_or_else(Error::input_exhausted)?;
432 let length = length
433 .to_usize()
434 .ok_or_else(|| Error::value_out_of_range(length, "usize"))?;
435
436 let mut result = Self::with_capacity(length);
437
438 for _ in 0..length {
439 result.push(T::decode_iter(iter)?);
440 }
441
442 Ok(result)
443 }
444}
445
446impl<'a, T, const N: usize> Decode<'a> for [T; N]
447where
448 T: Decode<'a> + Sized,
449{
450 fn decode_iter<I>(iter: &mut I) -> Result<Self, Error>
451 where
452 I: Iterator<Item = &'a Felt>,
453 {
454 let length = iter.next().ok_or_else(Error::input_exhausted)?;
455 let length = length
456 .to_usize()
457 .ok_or_else(|| Error::value_out_of_range(length, "usize"))?;
458
459 if length != N {
460 return Err(Error::length_mismatch(N, length));
461 }
462
463 let mut result: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
464
465 for elem in &mut result[..] {
466 *elem = MaybeUninit::new(T::decode_iter(iter)?);
467 }
468
469 Ok(unsafe { core::mem::transmute_copy::<_, [T; N]>(&result) })
470 }
471}
472
473impl Error {
474 pub fn input_exhausted() -> Self {
476 Self {
477 repr: "unexpected end of input stream"
478 .to_string()
479 .into_boxed_str(),
480 }
481 }
482
483 pub fn length_mismatch(expected: usize, actual: usize) -> Self {
486 Self {
487 repr: format!("expecting length `{expected}` but got `{actual}`").into_boxed_str(),
488 }
489 }
490
491 pub fn value_out_of_range<V>(value: V, type_name: &str) -> Self
493 where
494 V: Display,
495 {
496 Self {
497 repr: format!("value `{value}` is out of range for type `{type_name}`")
498 .into_boxed_str(),
499 }
500 }
501
502 pub fn unknown_enum_tag<V>(tag: V, type_name: &str) -> Self
504 where
505 V: Display,
506 {
507 Self {
508 repr: format!("enum tag `{tag}` is unknown for type `{type_name}`").into_boxed_str(),
509 }
510 }
511
512 pub fn custom<T>(content: T) -> Self
514 where
515 T: Display,
516 {
517 Self {
518 repr: content.to_string().into_boxed_str(),
519 }
520 }
521}
522
523#[cfg(feature = "std")]
524impl std::error::Error for Error {}
525
526impl Display for Error {
527 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
528 write!(f, "{}", self.repr)
529 }
530}
531
532#[cfg(test)]
533mod tests {
534 use core::str::FromStr;
535
536 use super::*;
537
538 #[test]
539 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
540 fn test_encode_felt() {
541 let mut serialized = Vec::<Felt>::new();
542 Felt::from_str("99999999999999999999999999")
543 .unwrap()
544 .encode(&mut serialized)
545 .unwrap();
546 assert_eq!(
547 serialized,
548 vec![Felt::from_str("99999999999999999999999999").unwrap()]
549 );
550 }
551
552 #[test]
553 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
554 fn test_encode_bool() {
555 let mut serialized = Vec::<Felt>::new();
556 true.encode(&mut serialized).unwrap();
557 assert_eq!(serialized, vec![Felt::from_str("1").unwrap()]);
558
559 let mut serialized = Vec::<Felt>::new();
560 false.encode(&mut serialized).unwrap();
561 assert_eq!(serialized, vec![Felt::from_str("0").unwrap()]);
562 }
563
564 #[test]
565 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
566 fn test_encode_u8() {
567 let mut serialized = Vec::<Felt>::new();
568 123u8.encode(&mut serialized).unwrap();
569 assert_eq!(serialized, vec![Felt::from_str("123").unwrap()]);
570 }
571
572 #[test]
573 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
574 fn test_encode_u16() {
575 let mut serialized = Vec::<Felt>::new();
576 12345u16.encode(&mut serialized).unwrap();
577 assert_eq!(serialized, vec![Felt::from_str("12345").unwrap()]);
578 }
579
580 #[test]
581 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
582 fn test_encode_u32() {
583 let mut serialized = Vec::<Felt>::new();
584 1234567890u32.encode(&mut serialized).unwrap();
585 assert_eq!(serialized, vec![Felt::from_str("1234567890").unwrap()]);
586 }
587
588 #[test]
589 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
590 fn test_encode_u64() {
591 let mut serialized = Vec::<Felt>::new();
592 12345678900000000000u64.encode(&mut serialized).unwrap();
593 assert_eq!(
594 serialized,
595 vec![Felt::from_str("12345678900000000000").unwrap()]
596 );
597 }
598
599 #[test]
600 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
601 fn test_encode_u128() {
602 let mut serialized = Vec::<Felt>::new();
603 123456789000000000000000000000u128
604 .encode(&mut serialized)
605 .unwrap();
606 assert_eq!(
607 serialized,
608 vec![Felt::from_str("123456789000000000000000000000").unwrap()]
609 );
610 }
611
612 #[test]
613 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
614 fn test_encode_i128() {
615 for (raw, felt) in [
616 (
617 0i128,
618 Felt::from_hex_unchecked(
619 "0x0000000000000000000000000000000000000000000000000000000000000000",
620 ),
621 ),
622 (
623 -1i128,
624 Felt::from_hex_unchecked(
625 "0x0800000000000011000000000000000000000000000000000000000000000000",
626 ),
627 ),
628 (
629 1i128,
630 Felt::from_hex_unchecked(
631 "0x0000000000000000000000000000000000000000000000000000000000000001",
632 ),
633 ),
634 (
635 10000i128,
636 Felt::from_hex_unchecked(
637 "0x0000000000000000000000000000000000000000000000000000000000002710",
638 ),
639 ),
640 (
641 -10000i128,
642 Felt::from_hex_unchecked(
643 "0x0800000000000010ffffffffffffffffffffffffffffffffffffffffffffd8f1",
644 ),
645 ),
646 (
647 i128::MIN,
648 Felt::from_hex_unchecked(
649 "0x0800000000000010ffffffffffffffff80000000000000000000000000000001",
650 ),
651 ),
652 (
653 i128::MIN + 1,
654 Felt::from_hex_unchecked(
655 "0x0800000000000010ffffffffffffffff80000000000000000000000000000002",
656 ),
657 ),
658 (
659 i128::MAX,
660 Felt::from_hex_unchecked(
661 "0x000000000000000000000000000000007fffffffffffffffffffffffffffffff",
662 ),
663 ),
664 (
665 i128::MAX - 1,
666 Felt::from_hex_unchecked(
667 "0x000000000000000000000000000000007ffffffffffffffffffffffffffffffe",
668 ),
669 ),
670 ] {
671 let mut serialized = Vec::<Felt>::new();
672 raw.encode(&mut serialized).unwrap();
673 assert_eq!(serialized, vec![felt]);
674 }
675 }
676
677 #[test]
678 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
679 fn test_encode_u256() {
680 let mut serialized = Vec::<Felt>::new();
681 U256::from_words(12345, 67890)
682 .encode(&mut serialized)
683 .unwrap();
684 assert_eq!(
685 serialized,
686 vec![
687 Felt::from_str("12345").unwrap(),
688 Felt::from_str("67890").unwrap()
689 ]
690 );
691 }
692
693 #[test]
694 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
695 fn test_encode_option() {
696 let mut serialized = Vec::<Felt>::new();
697 Some(10u32).encode(&mut serialized).unwrap();
698 assert_eq!(
699 serialized,
700 vec![Felt::from_str("0").unwrap(), Felt::from_str("10").unwrap()]
701 );
702
703 serialized.clear();
704 Option::<u32>::None.encode(&mut serialized).unwrap();
705 assert_eq!(serialized, vec![Felt::from_str("1").unwrap()]);
706 }
707
708 #[test]
709 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
710 fn test_encode_vec() {
711 let mut serialized = Vec::<Felt>::new();
712 vec![Some(10u32), None].encode(&mut serialized).unwrap();
713 assert_eq!(
714 serialized,
715 vec![
716 Felt::from_str("2").unwrap(),
717 Felt::from_str("0").unwrap(),
718 Felt::from_str("10").unwrap(),
719 Felt::from_str("1").unwrap()
720 ]
721 );
722 }
723
724 #[test]
725 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
726 fn test_encode_array() {
727 let mut serialized = Vec::<Felt>::new();
728 <[Option<u32>; 2]>::encode(&[Some(10u32), None], &mut serialized).unwrap();
729 assert_eq!(
730 serialized,
731 vec![
732 Felt::from_str("2").unwrap(),
733 Felt::from_str("0").unwrap(),
734 Felt::from_str("10").unwrap(),
735 Felt::from_str("1").unwrap()
736 ]
737 );
738 }
739
740 #[test]
741 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
742 fn test_encode_slice() {
743 let mut serialized = Vec::<Felt>::new();
744 <[Option<u32>]>::encode(&[Some(10u32), None], &mut serialized).unwrap();
745 assert_eq!(
746 serialized,
747 vec![
748 Felt::from_str("2").unwrap(),
749 Felt::from_str("0").unwrap(),
750 Felt::from_str("10").unwrap(),
751 Felt::from_str("1").unwrap()
752 ]
753 );
754 }
755
756 #[test]
757 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
758 fn test_derive_encode_struct_named() {
759 #[derive(Encode)]
760 #[starknet(core = "crate")]
761 struct CairoType {
762 a: Felt,
763 b: U256,
764 c: bool,
765 }
766
767 let mut serialized = Vec::<Felt>::new();
768 CairoType {
769 a: Felt::from_str("12345").unwrap(),
770 b: U256::from_words(12, 34),
771 c: true,
772 }
773 .encode(&mut serialized)
774 .unwrap();
775 assert_eq!(
776 serialized,
777 vec![
778 Felt::from_str("12345").unwrap(),
779 Felt::from_str("12").unwrap(),
780 Felt::from_str("34").unwrap(),
781 Felt::from_str("1").unwrap(),
782 ]
783 );
784 }
785
786 #[test]
787 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
788 fn test_derive_encode_struct_tuple() {
789 #[derive(Encode)]
790 #[starknet(core = "crate")]
791 struct CairoType(Felt, U256, bool);
792
793 let mut serialized = Vec::<Felt>::new();
794 CairoType(
795 Felt::from_str("12345").unwrap(),
796 U256::from_words(12, 34),
797 true,
798 )
799 .encode(&mut serialized)
800 .unwrap();
801 assert_eq!(
802 serialized,
803 vec![
804 Felt::from_str("12345").unwrap(),
805 Felt::from_str("12").unwrap(),
806 Felt::from_str("34").unwrap(),
807 Felt::from_str("1").unwrap(),
808 ]
809 );
810 }
811
812 #[test]
813 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
814 fn test_derive_encode_enum() {
815 #[derive(Encode)]
816 #[starknet(core = "crate")]
817 enum CairoType {
818 A,
819 B(bool),
820 C(Option<U256>, u8),
821 D { a: u64, b: bool },
822 }
823
824 let mut serialized = Vec::<Felt>::new();
825 CairoType::A.encode(&mut serialized).unwrap();
826 assert_eq!(serialized, vec![Felt::from_str("0").unwrap()]);
827
828 serialized.clear();
829 CairoType::B(true).encode(&mut serialized).unwrap();
830 assert_eq!(
831 serialized,
832 vec![Felt::from_str("1").unwrap(), Felt::from_str("1").unwrap()]
833 );
834
835 serialized.clear();
836 CairoType::C(Some(U256::from_words(12, 23)), 4)
837 .encode(&mut serialized)
838 .unwrap();
839 assert_eq!(
840 serialized,
841 vec![
842 Felt::from_str("2").unwrap(),
843 Felt::from_str("0").unwrap(),
844 Felt::from_str("12").unwrap(),
845 Felt::from_str("23").unwrap(),
846 Felt::from_str("4").unwrap(),
847 ]
848 );
849
850 serialized.clear();
851 CairoType::C(None, 8).encode(&mut serialized).unwrap();
852 assert_eq!(
853 serialized,
854 vec![
855 Felt::from_str("2").unwrap(),
856 Felt::from_str("1").unwrap(),
857 Felt::from_str("8").unwrap(),
858 ]
859 );
860
861 serialized.clear();
862 CairoType::D { a: 100, b: false }
863 .encode(&mut serialized)
864 .unwrap();
865 assert_eq!(
866 serialized,
867 vec![
868 Felt::from_str("3").unwrap(),
869 Felt::from_str("100").unwrap(),
870 Felt::from_str("0").unwrap()
871 ]
872 );
873 }
874
875 #[test]
876 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
877 fn test_decode_felt() {
878 assert_eq!(
879 Felt::from_str("99999999999999999999999999").unwrap(),
880 Felt::decode(&[Felt::from_str("99999999999999999999999999").unwrap()]).unwrap()
881 );
882 }
883
884 #[allow(clippy::bool_assert_comparison)]
885 #[test]
886 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
887 fn test_decode_bool() {
888 assert_eq!(true, bool::decode(&[Felt::from_str("1").unwrap()]).unwrap());
889
890 assert_eq!(
891 false,
892 bool::decode(&[Felt::from_str("0").unwrap()]).unwrap()
893 );
894 }
895
896 #[test]
897 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
898 fn test_decode_u8() {
899 assert_eq!(
900 123u8,
901 u8::decode(&[Felt::from_str("123").unwrap()]).unwrap()
902 );
903 }
904
905 #[test]
906 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
907 fn test_decode_u16() {
908 assert_eq!(
909 12345u16,
910 u16::decode(&[Felt::from_str("12345").unwrap()]).unwrap()
911 );
912 }
913
914 #[test]
915 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
916 fn test_decode_u32() {
917 assert_eq!(
918 1234567890u32,
919 u32::decode(&[Felt::from_str("1234567890").unwrap()]).unwrap()
920 );
921 }
922
923 #[test]
924 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
925 fn test_decode_u64() {
926 assert_eq!(
927 12345678900000000000u64,
928 u64::decode(&[Felt::from_str("12345678900000000000").unwrap()]).unwrap()
929 );
930 }
931
932 #[test]
933 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
934 fn test_decode_u128() {
935 assert_eq!(
936 123456789000000000000000000000u128,
937 u128::decode(&[Felt::from_str("123456789000000000000000000000").unwrap()]).unwrap()
938 );
939 }
940
941 #[test]
942 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
943 fn test_decode_i128() {
944 for (raw, felt) in [
945 (
946 0i128,
947 Felt::from_hex_unchecked(
948 "0x0000000000000000000000000000000000000000000000000000000000000000",
949 ),
950 ),
951 (
952 -1i128,
953 Felt::from_hex_unchecked(
954 "0x0800000000000011000000000000000000000000000000000000000000000000",
955 ),
956 ),
957 (
958 1i128,
959 Felt::from_hex_unchecked(
960 "0x0000000000000000000000000000000000000000000000000000000000000001",
961 ),
962 ),
963 (
964 10000i128,
965 Felt::from_hex_unchecked(
966 "0x0000000000000000000000000000000000000000000000000000000000002710",
967 ),
968 ),
969 (
970 -10000i128,
971 Felt::from_hex_unchecked(
972 "0x0800000000000010ffffffffffffffffffffffffffffffffffffffffffffd8f1",
973 ),
974 ),
975 (
976 i128::MIN,
977 Felt::from_hex_unchecked(
978 "0x0800000000000010ffffffffffffffff80000000000000000000000000000001",
979 ),
980 ),
981 (
982 i128::MIN + 1,
983 Felt::from_hex_unchecked(
984 "0x0800000000000010ffffffffffffffff80000000000000000000000000000002",
985 ),
986 ),
987 (
988 i128::MAX,
989 Felt::from_hex_unchecked(
990 "0x000000000000000000000000000000007fffffffffffffffffffffffffffffff",
991 ),
992 ),
993 (
994 i128::MAX - 1,
995 Felt::from_hex_unchecked(
996 "0x000000000000000000000000000000007ffffffffffffffffffffffffffffffe",
997 ),
998 ),
999 ] {
1000 assert_eq!(raw, i128::decode(&[felt]).unwrap());
1001 }
1002 }
1003
1004 #[test]
1005 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1006 fn test_decode_u256() {
1007 assert_eq!(
1008 U256::from_words(12345, 67890),
1009 U256::decode(&[
1010 Felt::from_str("12345").unwrap(),
1011 Felt::from_str("67890").unwrap()
1012 ])
1013 .unwrap()
1014 );
1015 }
1016
1017 #[test]
1018 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1019 fn test_decode_option() {
1020 assert_eq!(
1021 Some(10u32),
1022 Option::<u32>::decode(&[Felt::from_str("0").unwrap(), Felt::from_str("10").unwrap()])
1023 .unwrap()
1024 );
1025
1026 assert_eq!(
1027 Option::<u32>::None,
1028 Option::<u32>::decode(&[Felt::from_str("1").unwrap()]).unwrap()
1029 );
1030 }
1031
1032 #[test]
1033 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1034 fn test_decode_vec() {
1035 assert_eq!(
1036 vec![Some(10u32), None],
1037 Vec::<Option::<u32>>::decode(&[
1038 Felt::from_str("2").unwrap(),
1039 Felt::from_str("0").unwrap(),
1040 Felt::from_str("10").unwrap(),
1041 Felt::from_str("1").unwrap()
1042 ])
1043 .unwrap()
1044 );
1045 }
1046
1047 #[test]
1048 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1049 fn test_decode_array() {
1050 assert_eq!(
1051 [Some(10u32), None],
1052 <[Option<u32>; 2]>::decode(&[
1053 Felt::from_str("2").unwrap(),
1054 Felt::from_str("0").unwrap(),
1055 Felt::from_str("10").unwrap(),
1056 Felt::from_str("1").unwrap()
1057 ])
1058 .unwrap()
1059 );
1060 }
1061
1062 #[test]
1063 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1064 fn test_derive_decode_struct_named() {
1065 #[derive(Debug, PartialEq, Eq, Decode)]
1066 #[starknet(core = "crate")]
1067 struct CairoType {
1068 a: Felt,
1069 b: U256,
1070 c: bool,
1071 }
1072
1073 assert_eq!(
1074 CairoType {
1075 a: Felt::from_str("12345").unwrap(),
1076 b: U256::from_words(12, 34),
1077 c: true,
1078 },
1079 CairoType::decode(&[
1080 Felt::from_str("12345").unwrap(),
1081 Felt::from_str("12").unwrap(),
1082 Felt::from_str("34").unwrap(),
1083 Felt::from_str("1").unwrap(),
1084 ])
1085 .unwrap()
1086 );
1087 }
1088
1089 #[test]
1090 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1091 fn test_derive_decode_struct_tuple() {
1092 #[derive(Debug, PartialEq, Eq, Decode)]
1093 #[starknet(core = "crate")]
1094 struct CairoType(Felt, U256, bool);
1095
1096 assert_eq!(
1097 CairoType(
1098 Felt::from_str("12345").unwrap(),
1099 U256::from_words(12, 34),
1100 true,
1101 ),
1102 CairoType::decode(&[
1103 Felt::from_str("12345").unwrap(),
1104 Felt::from_str("12").unwrap(),
1105 Felt::from_str("34").unwrap(),
1106 Felt::from_str("1").unwrap(),
1107 ])
1108 .unwrap()
1109 );
1110 }
1111
1112 #[test]
1113 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1114 fn test_derive_decode_enum() {
1115 #[derive(Debug, PartialEq, Eq, Decode)]
1116 #[starknet(core = "crate")]
1117 enum CairoType {
1118 A,
1119 B(bool),
1120 C(Option<U256>, u8),
1121 D { a: u64, b: bool },
1122 }
1123
1124 assert_eq!(
1125 CairoType::A,
1126 CairoType::decode(&[Felt::from_str("0").unwrap()]).unwrap()
1127 );
1128
1129 assert_eq!(
1130 CairoType::B(true),
1131 CairoType::decode(&[Felt::from_str("1").unwrap(), Felt::from_str("1").unwrap()])
1132 .unwrap()
1133 );
1134
1135 assert_eq!(
1136 CairoType::C(Some(U256::from_words(12, 23)), 4),
1137 CairoType::decode(&[
1138 Felt::from_str("2").unwrap(),
1139 Felt::from_str("0").unwrap(),
1140 Felt::from_str("12").unwrap(),
1141 Felt::from_str("23").unwrap(),
1142 Felt::from_str("4").unwrap(),
1143 ])
1144 .unwrap()
1145 );
1146
1147 assert_eq!(
1148 CairoType::C(None, 8),
1149 CairoType::decode(&[
1150 Felt::from_str("2").unwrap(),
1151 Felt::from_str("1").unwrap(),
1152 Felt::from_str("8").unwrap(),
1153 ])
1154 .unwrap()
1155 );
1156
1157 assert_eq!(
1158 CairoType::D { a: 100, b: false },
1159 CairoType::decode(&[
1160 Felt::from_str("3").unwrap(),
1161 Felt::from_str("100").unwrap(),
1162 Felt::from_str("0").unwrap()
1163 ])
1164 .unwrap()
1165 );
1166 }
1167}