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