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 `{}` but got `{}`", expected, 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 `{}` is out of range for type `{}`", value, 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 `{}` is unknown for type `{}`", tag, type_name)
503 .into_boxed_str(),
504 }
505 }
506
507 pub fn custom<T>(content: T) -> Self
509 where
510 T: Display,
511 {
512 Self {
513 repr: content.to_string().into_boxed_str(),
514 }
515 }
516}
517
518#[cfg(feature = "std")]
519impl std::error::Error for Error {}
520
521impl Display for Error {
522 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
523 write!(f, "{}", self.repr)
524 }
525}
526
527#[cfg(test)]
528mod tests {
529 use core::str::FromStr;
530
531 use super::*;
532
533 #[test]
534 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
535 fn test_encode_felt() {
536 let mut serialized = Vec::<Felt>::new();
537 Felt::from_str("99999999999999999999999999")
538 .unwrap()
539 .encode(&mut serialized)
540 .unwrap();
541 assert_eq!(
542 serialized,
543 vec![Felt::from_str("99999999999999999999999999").unwrap()]
544 );
545 }
546
547 #[test]
548 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
549 fn test_encode_bool() {
550 let mut serialized = Vec::<Felt>::new();
551 true.encode(&mut serialized).unwrap();
552 assert_eq!(serialized, vec![Felt::from_str("1").unwrap()]);
553
554 let mut serialized = Vec::<Felt>::new();
555 false.encode(&mut serialized).unwrap();
556 assert_eq!(serialized, vec![Felt::from_str("0").unwrap()]);
557 }
558
559 #[test]
560 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
561 fn test_encode_u8() {
562 let mut serialized = Vec::<Felt>::new();
563 123u8.encode(&mut serialized).unwrap();
564 assert_eq!(serialized, vec![Felt::from_str("123").unwrap()]);
565 }
566
567 #[test]
568 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
569 fn test_encode_u16() {
570 let mut serialized = Vec::<Felt>::new();
571 12345u16.encode(&mut serialized).unwrap();
572 assert_eq!(serialized, vec![Felt::from_str("12345").unwrap()]);
573 }
574
575 #[test]
576 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
577 fn test_encode_u32() {
578 let mut serialized = Vec::<Felt>::new();
579 1234567890u32.encode(&mut serialized).unwrap();
580 assert_eq!(serialized, vec![Felt::from_str("1234567890").unwrap()]);
581 }
582
583 #[test]
584 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
585 fn test_encode_u64() {
586 let mut serialized = Vec::<Felt>::new();
587 12345678900000000000u64.encode(&mut serialized).unwrap();
588 assert_eq!(
589 serialized,
590 vec![Felt::from_str("12345678900000000000").unwrap()]
591 );
592 }
593
594 #[test]
595 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
596 fn test_encode_u128() {
597 let mut serialized = Vec::<Felt>::new();
598 123456789000000000000000000000u128
599 .encode(&mut serialized)
600 .unwrap();
601 assert_eq!(
602 serialized,
603 vec![Felt::from_str("123456789000000000000000000000").unwrap()]
604 );
605 }
606
607 #[test]
608 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
609 fn test_encode_i128() {
610 for (raw, felt) in [
611 (
612 0i128,
613 Felt::from_hex_unchecked(
614 "0x0000000000000000000000000000000000000000000000000000000000000000",
615 ),
616 ),
617 (
618 -1i128,
619 Felt::from_hex_unchecked(
620 "0x0800000000000011000000000000000000000000000000000000000000000000",
621 ),
622 ),
623 (
624 1i128,
625 Felt::from_hex_unchecked(
626 "0x0000000000000000000000000000000000000000000000000000000000000001",
627 ),
628 ),
629 (
630 10000i128,
631 Felt::from_hex_unchecked(
632 "0x0000000000000000000000000000000000000000000000000000000000002710",
633 ),
634 ),
635 (
636 -10000i128,
637 Felt::from_hex_unchecked(
638 "0x0800000000000010ffffffffffffffffffffffffffffffffffffffffffffd8f1",
639 ),
640 ),
641 (
642 i128::MIN,
643 Felt::from_hex_unchecked(
644 "0x0800000000000010ffffffffffffffff80000000000000000000000000000001",
645 ),
646 ),
647 (
648 i128::MIN + 1,
649 Felt::from_hex_unchecked(
650 "0x0800000000000010ffffffffffffffff80000000000000000000000000000002",
651 ),
652 ),
653 (
654 i128::MAX,
655 Felt::from_hex_unchecked(
656 "0x000000000000000000000000000000007fffffffffffffffffffffffffffffff",
657 ),
658 ),
659 (
660 i128::MAX - 1,
661 Felt::from_hex_unchecked(
662 "0x000000000000000000000000000000007ffffffffffffffffffffffffffffffe",
663 ),
664 ),
665 ] {
666 let mut serialized = Vec::<Felt>::new();
667 raw.encode(&mut serialized).unwrap();
668 assert_eq!(serialized, vec![felt]);
669 }
670 }
671
672 #[test]
673 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
674 fn test_encode_u256() {
675 let mut serialized = Vec::<Felt>::new();
676 U256::from_words(12345, 67890)
677 .encode(&mut serialized)
678 .unwrap();
679 assert_eq!(
680 serialized,
681 vec![
682 Felt::from_str("12345").unwrap(),
683 Felt::from_str("67890").unwrap()
684 ]
685 );
686 }
687
688 #[test]
689 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
690 fn test_encode_option() {
691 let mut serialized = Vec::<Felt>::new();
692 Some(10u32).encode(&mut serialized).unwrap();
693 assert_eq!(
694 serialized,
695 vec![Felt::from_str("0").unwrap(), Felt::from_str("10").unwrap()]
696 );
697
698 serialized.clear();
699 Option::<u32>::None.encode(&mut serialized).unwrap();
700 assert_eq!(serialized, vec![Felt::from_str("1").unwrap()]);
701 }
702
703 #[test]
704 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
705 fn test_encode_vec() {
706 let mut serialized = Vec::<Felt>::new();
707 vec![Some(10u32), None].encode(&mut serialized).unwrap();
708 assert_eq!(
709 serialized,
710 vec![
711 Felt::from_str("2").unwrap(),
712 Felt::from_str("0").unwrap(),
713 Felt::from_str("10").unwrap(),
714 Felt::from_str("1").unwrap()
715 ]
716 );
717 }
718
719 #[test]
720 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
721 fn test_encode_array() {
722 let mut serialized = Vec::<Felt>::new();
723 <[Option<u32>; 2]>::encode(&[Some(10u32), None], &mut serialized).unwrap();
724 assert_eq!(
725 serialized,
726 vec![
727 Felt::from_str("2").unwrap(),
728 Felt::from_str("0").unwrap(),
729 Felt::from_str("10").unwrap(),
730 Felt::from_str("1").unwrap()
731 ]
732 );
733 }
734
735 #[test]
736 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
737 fn test_encode_slice() {
738 let mut serialized = Vec::<Felt>::new();
739 <[Option<u32>]>::encode(&[Some(10u32), None], &mut serialized).unwrap();
740 assert_eq!(
741 serialized,
742 vec![
743 Felt::from_str("2").unwrap(),
744 Felt::from_str("0").unwrap(),
745 Felt::from_str("10").unwrap(),
746 Felt::from_str("1").unwrap()
747 ]
748 );
749 }
750
751 #[test]
752 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
753 fn test_derive_encode_struct_named() {
754 #[derive(Encode)]
755 #[starknet(core = "crate")]
756 struct CairoType {
757 a: Felt,
758 b: U256,
759 c: bool,
760 }
761
762 let mut serialized = Vec::<Felt>::new();
763 CairoType {
764 a: Felt::from_str("12345").unwrap(),
765 b: U256::from_words(12, 34),
766 c: true,
767 }
768 .encode(&mut serialized)
769 .unwrap();
770 assert_eq!(
771 serialized,
772 vec![
773 Felt::from_str("12345").unwrap(),
774 Felt::from_str("12").unwrap(),
775 Felt::from_str("34").unwrap(),
776 Felt::from_str("1").unwrap(),
777 ]
778 );
779 }
780
781 #[test]
782 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
783 fn test_derive_encode_struct_tuple() {
784 #[derive(Encode)]
785 #[starknet(core = "crate")]
786 struct CairoType(Felt, U256, bool);
787
788 let mut serialized = Vec::<Felt>::new();
789 CairoType(
790 Felt::from_str("12345").unwrap(),
791 U256::from_words(12, 34),
792 true,
793 )
794 .encode(&mut serialized)
795 .unwrap();
796 assert_eq!(
797 serialized,
798 vec![
799 Felt::from_str("12345").unwrap(),
800 Felt::from_str("12").unwrap(),
801 Felt::from_str("34").unwrap(),
802 Felt::from_str("1").unwrap(),
803 ]
804 );
805 }
806
807 #[test]
808 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
809 fn test_derive_encode_enum() {
810 #[derive(Encode)]
811 #[starknet(core = "crate")]
812 enum CairoType {
813 A,
814 B(bool),
815 C(Option<U256>, u8),
816 D { a: u64, b: bool },
817 }
818
819 let mut serialized = Vec::<Felt>::new();
820 CairoType::A.encode(&mut serialized).unwrap();
821 assert_eq!(serialized, vec![Felt::from_str("0").unwrap()]);
822
823 serialized.clear();
824 CairoType::B(true).encode(&mut serialized).unwrap();
825 assert_eq!(
826 serialized,
827 vec![Felt::from_str("1").unwrap(), Felt::from_str("1").unwrap()]
828 );
829
830 serialized.clear();
831 CairoType::C(Some(U256::from_words(12, 23)), 4)
832 .encode(&mut serialized)
833 .unwrap();
834 assert_eq!(
835 serialized,
836 vec![
837 Felt::from_str("2").unwrap(),
838 Felt::from_str("0").unwrap(),
839 Felt::from_str("12").unwrap(),
840 Felt::from_str("23").unwrap(),
841 Felt::from_str("4").unwrap(),
842 ]
843 );
844
845 serialized.clear();
846 CairoType::C(None, 8).encode(&mut serialized).unwrap();
847 assert_eq!(
848 serialized,
849 vec![
850 Felt::from_str("2").unwrap(),
851 Felt::from_str("1").unwrap(),
852 Felt::from_str("8").unwrap(),
853 ]
854 );
855
856 serialized.clear();
857 CairoType::D { a: 100, b: false }
858 .encode(&mut serialized)
859 .unwrap();
860 assert_eq!(
861 serialized,
862 vec![
863 Felt::from_str("3").unwrap(),
864 Felt::from_str("100").unwrap(),
865 Felt::from_str("0").unwrap()
866 ]
867 );
868 }
869
870 #[test]
871 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
872 fn test_decode_felt() {
873 assert_eq!(
874 Felt::from_str("99999999999999999999999999").unwrap(),
875 Felt::decode(&[Felt::from_str("99999999999999999999999999").unwrap()]).unwrap()
876 );
877 }
878
879 #[allow(clippy::bool_assert_comparison)]
880 #[test]
881 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
882 fn test_decode_bool() {
883 assert_eq!(true, bool::decode(&[Felt::from_str("1").unwrap()]).unwrap());
884
885 assert_eq!(
886 false,
887 bool::decode(&[Felt::from_str("0").unwrap()]).unwrap()
888 );
889 }
890
891 #[test]
892 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
893 fn test_decode_u8() {
894 assert_eq!(
895 123u8,
896 u8::decode(&[Felt::from_str("123").unwrap()]).unwrap()
897 );
898 }
899
900 #[test]
901 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
902 fn test_decode_u16() {
903 assert_eq!(
904 12345u16,
905 u16::decode(&[Felt::from_str("12345").unwrap()]).unwrap()
906 );
907 }
908
909 #[test]
910 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
911 fn test_decode_u32() {
912 assert_eq!(
913 1234567890u32,
914 u32::decode(&[Felt::from_str("1234567890").unwrap()]).unwrap()
915 );
916 }
917
918 #[test]
919 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
920 fn test_decode_u64() {
921 assert_eq!(
922 12345678900000000000u64,
923 u64::decode(&[Felt::from_str("12345678900000000000").unwrap()]).unwrap()
924 );
925 }
926
927 #[test]
928 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
929 fn test_decode_u128() {
930 assert_eq!(
931 123456789000000000000000000000u128,
932 u128::decode(&[Felt::from_str("123456789000000000000000000000").unwrap()]).unwrap()
933 );
934 }
935
936 #[test]
937 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
938 fn test_decode_i128() {
939 for (raw, felt) in [
940 (
941 0i128,
942 Felt::from_hex_unchecked(
943 "0x0000000000000000000000000000000000000000000000000000000000000000",
944 ),
945 ),
946 (
947 -1i128,
948 Felt::from_hex_unchecked(
949 "0x0800000000000011000000000000000000000000000000000000000000000000",
950 ),
951 ),
952 (
953 1i128,
954 Felt::from_hex_unchecked(
955 "0x0000000000000000000000000000000000000000000000000000000000000001",
956 ),
957 ),
958 (
959 10000i128,
960 Felt::from_hex_unchecked(
961 "0x0000000000000000000000000000000000000000000000000000000000002710",
962 ),
963 ),
964 (
965 -10000i128,
966 Felt::from_hex_unchecked(
967 "0x0800000000000010ffffffffffffffffffffffffffffffffffffffffffffd8f1",
968 ),
969 ),
970 (
971 i128::MIN,
972 Felt::from_hex_unchecked(
973 "0x0800000000000010ffffffffffffffff80000000000000000000000000000001",
974 ),
975 ),
976 (
977 i128::MIN + 1,
978 Felt::from_hex_unchecked(
979 "0x0800000000000010ffffffffffffffff80000000000000000000000000000002",
980 ),
981 ),
982 (
983 i128::MAX,
984 Felt::from_hex_unchecked(
985 "0x000000000000000000000000000000007fffffffffffffffffffffffffffffff",
986 ),
987 ),
988 (
989 i128::MAX - 1,
990 Felt::from_hex_unchecked(
991 "0x000000000000000000000000000000007ffffffffffffffffffffffffffffffe",
992 ),
993 ),
994 ] {
995 assert_eq!(raw, i128::decode(&[felt]).unwrap());
996 }
997 }
998
999 #[test]
1000 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1001 fn test_decode_u256() {
1002 assert_eq!(
1003 U256::from_words(12345, 67890),
1004 U256::decode(&[
1005 Felt::from_str("12345").unwrap(),
1006 Felt::from_str("67890").unwrap()
1007 ])
1008 .unwrap()
1009 );
1010 }
1011
1012 #[test]
1013 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1014 fn test_decode_option() {
1015 assert_eq!(
1016 Some(10u32),
1017 Option::<u32>::decode(&[Felt::from_str("0").unwrap(), Felt::from_str("10").unwrap()])
1018 .unwrap()
1019 );
1020
1021 assert_eq!(
1022 Option::<u32>::None,
1023 Option::<u32>::decode(&[Felt::from_str("1").unwrap()]).unwrap()
1024 );
1025 }
1026
1027 #[test]
1028 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1029 fn test_decode_vec() {
1030 assert_eq!(
1031 vec![Some(10u32), None],
1032 Vec::<Option::<u32>>::decode(&[
1033 Felt::from_str("2").unwrap(),
1034 Felt::from_str("0").unwrap(),
1035 Felt::from_str("10").unwrap(),
1036 Felt::from_str("1").unwrap()
1037 ])
1038 .unwrap()
1039 );
1040 }
1041
1042 #[test]
1043 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1044 fn test_decode_array() {
1045 assert_eq!(
1046 [Some(10u32), None],
1047 <[Option<u32>; 2]>::decode(&[
1048 Felt::from_str("2").unwrap(),
1049 Felt::from_str("0").unwrap(),
1050 Felt::from_str("10").unwrap(),
1051 Felt::from_str("1").unwrap()
1052 ])
1053 .unwrap()
1054 );
1055 }
1056
1057 #[test]
1058 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1059 fn test_derive_decode_struct_named() {
1060 #[derive(Debug, PartialEq, Eq, Decode)]
1061 #[starknet(core = "crate")]
1062 struct CairoType {
1063 a: Felt,
1064 b: U256,
1065 c: bool,
1066 }
1067
1068 assert_eq!(
1069 CairoType {
1070 a: Felt::from_str("12345").unwrap(),
1071 b: U256::from_words(12, 34),
1072 c: true,
1073 },
1074 CairoType::decode(&[
1075 Felt::from_str("12345").unwrap(),
1076 Felt::from_str("12").unwrap(),
1077 Felt::from_str("34").unwrap(),
1078 Felt::from_str("1").unwrap(),
1079 ])
1080 .unwrap()
1081 );
1082 }
1083
1084 #[test]
1085 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1086 fn test_derive_decode_struct_tuple() {
1087 #[derive(Debug, PartialEq, Eq, Decode)]
1088 #[starknet(core = "crate")]
1089 struct CairoType(Felt, U256, bool);
1090
1091 assert_eq!(
1092 CairoType(
1093 Felt::from_str("12345").unwrap(),
1094 U256::from_words(12, 34),
1095 true,
1096 ),
1097 CairoType::decode(&[
1098 Felt::from_str("12345").unwrap(),
1099 Felt::from_str("12").unwrap(),
1100 Felt::from_str("34").unwrap(),
1101 Felt::from_str("1").unwrap(),
1102 ])
1103 .unwrap()
1104 );
1105 }
1106
1107 #[test]
1108 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1109 fn test_derive_decode_enum() {
1110 #[derive(Debug, PartialEq, Eq, Decode)]
1111 #[starknet(core = "crate")]
1112 enum CairoType {
1113 A,
1114 B(bool),
1115 C(Option<U256>, u8),
1116 D { a: u64, b: bool },
1117 }
1118
1119 assert_eq!(
1120 CairoType::A,
1121 CairoType::decode(&[Felt::from_str("0").unwrap()]).unwrap()
1122 );
1123
1124 assert_eq!(
1125 CairoType::B(true),
1126 CairoType::decode(&[Felt::from_str("1").unwrap(), Felt::from_str("1").unwrap()])
1127 .unwrap()
1128 );
1129
1130 assert_eq!(
1131 CairoType::C(Some(U256::from_words(12, 23)), 4),
1132 CairoType::decode(&[
1133 Felt::from_str("2").unwrap(),
1134 Felt::from_str("0").unwrap(),
1135 Felt::from_str("12").unwrap(),
1136 Felt::from_str("23").unwrap(),
1137 Felt::from_str("4").unwrap(),
1138 ])
1139 .unwrap()
1140 );
1141
1142 assert_eq!(
1143 CairoType::C(None, 8),
1144 CairoType::decode(&[
1145 Felt::from_str("2").unwrap(),
1146 Felt::from_str("1").unwrap(),
1147 Felt::from_str("8").unwrap(),
1148 ])
1149 .unwrap()
1150 );
1151
1152 assert_eq!(
1153 CairoType::D { a: 100, b: false },
1154 CairoType::decode(&[
1155 Felt::from_str("3").unwrap(),
1156 Felt::from_str("100").unwrap(),
1157 Felt::from_str("0").unwrap()
1158 ])
1159 .unwrap()
1160 );
1161 }
1162}