1use crate::{impls::*, traits::*, types::*};
7#[cfg(not(feature = "std"))]
8use alloc::boxed::Box;
9#[cfg(not(feature = "std"))]
10use alloc::{collections, string::String, vec::Vec};
11use collections::{BTreeMap, BTreeSet};
12#[cfg(not(feature = "std"))]
13use core::{
14 convert::{TryFrom, TryInto},
15 num::TryFromIntError,
16};
17#[cfg(feature = "derive-serde")]
18pub use impls::VersionedSchemaError;
19#[cfg(feature = "std")]
21use std::{
22 collections,
23 convert::{TryFrom, TryInto},
24 num::TryFromIntError,
25};
26
27pub trait SchemaType {
35 fn get_type() -> crate::schema::Type;
36}
37
38#[derive(Debug, Clone, PartialEq, Eq)]
43pub struct ModuleV0 {
44 pub contracts: BTreeMap<String, ContractV0>,
45}
46
47#[derive(Debug, Clone, PartialEq, Eq)]
52pub struct ModuleV1 {
53 pub contracts: BTreeMap<String, ContractV1>,
54}
55
56#[derive(Debug, Clone, PartialEq, Eq)]
59pub struct ModuleV2 {
60 pub contracts: BTreeMap<String, ContractV2>,
61}
62
63#[cfg_attr(test, derive(arbitrary::Arbitrary))]
66#[derive(Debug, Clone, PartialEq, Eq)]
67pub struct ModuleV3 {
68 pub contracts: BTreeMap<String, ContractV3>,
69}
70
71#[derive(Debug, Clone)]
80pub enum VersionedModuleSchema {
81 V0(ModuleV0),
83 V1(ModuleV1),
85 V2(ModuleV2),
87 V3(ModuleV3),
89}
90
91#[derive(Debug, Default, Clone, PartialEq, Eq)]
94pub struct ContractV0 {
95 pub state: Option<Type>,
96 pub init: Option<Type>,
97 pub receive: BTreeMap<String, Type>,
98}
99
100#[derive(Debug, Default, Clone, PartialEq, Eq)]
102pub struct ContractV1 {
104 pub init: Option<FunctionV1>,
105 pub receive: BTreeMap<String, FunctionV1>,
106}
107
108#[derive(Debug, Default, Clone, PartialEq, Eq)]
110pub struct ContractV2 {
112 pub init: Option<FunctionV2>,
113 pub receive: BTreeMap<String, FunctionV2>,
114}
115
116#[cfg_attr(test, derive(arbitrary::Arbitrary))]
118#[derive(Debug, Default, Clone, PartialEq, Eq)]
119pub struct ContractV3 {
121 pub init: Option<FunctionV2>,
122 pub receive: BTreeMap<String, FunctionV2>,
123 pub event: Option<Type>,
124}
125
126impl ContractV3 {
127 pub fn event(&self) -> Option<&Type> { self.event.as_ref() }
129}
130
131#[derive(Debug, Clone, PartialEq, Eq)]
134pub enum FunctionV1 {
135 Parameter(Type),
136 ReturnValue(Type),
137 Both {
138 parameter: Type,
139 return_value: Type,
140 },
141}
142
143impl FunctionV1 {
144 pub fn parameter(&self) -> Option<&Type> {
146 match self {
147 FunctionV1::Parameter(ty) => Some(ty),
148 FunctionV1::ReturnValue(_) => None,
149 FunctionV1::Both {
150 parameter,
151 ..
152 } => Some(parameter),
153 }
154 }
155
156 pub fn return_value(&self) -> Option<&Type> {
158 match self {
159 FunctionV1::Parameter(_) => None,
160 FunctionV1::ReturnValue(rv) => Some(rv),
161 FunctionV1::Both {
162 return_value,
163 ..
164 } => Some(return_value),
165 }
166 }
167}
168
169#[cfg_attr(test, derive(arbitrary::Arbitrary))]
173#[derive(Debug, Clone, PartialEq, Eq)]
174pub struct FunctionV2 {
175 pub parameter: Option<Type>,
176 pub return_value: Option<Type>,
177 pub error: Option<Type>,
178}
179
180impl FunctionV2 {
181 pub fn parameter(&self) -> Option<&Type> { self.parameter.as_ref() }
183
184 pub fn return_value(&self) -> Option<&Type> { self.return_value.as_ref() }
186
187 pub fn error(&self) -> Option<&Type> { self.error.as_ref() }
189}
190
191#[derive(Debug, Clone, PartialEq, Eq)]
193#[cfg_attr(test, derive(arbitrary::Arbitrary))]
194pub enum Fields {
195 Named(Vec<(String, Type)>),
197 Unnamed(Vec<Type>),
199 None,
204}
205
206#[derive(Debug, Copy, Clone, PartialEq, Eq)]
208#[cfg_attr(test, derive(arbitrary::Arbitrary))]
209pub enum SizeLength {
210 U8,
211 U16,
212 U32,
213 U64,
214}
215
216#[derive(Debug, Clone, PartialEq, Eq)]
219#[cfg_attr(test, derive(arbitrary::Arbitrary))]
220pub enum Type {
221 Unit,
223 Bool,
225 U8,
227 U16,
229 U32,
231 U64,
233 U128,
235 I8,
237 I16,
239 I32,
241 I64,
243 I128,
245 Amount,
247 AccountAddress,
249 ContractAddress,
251 Timestamp,
254 Duration,
257 Pair(Box<Type>, Box<Type>),
259 List(SizeLength, Box<Type>),
262 Set(SizeLength, Box<Type>),
265 Map(SizeLength, Box<Type>, Box<Type>),
268 Array(u32, Box<Type>),
270 Struct(Fields),
272 Enum(Vec<(String, Fields)>),
274 String(SizeLength),
277 ContractName(SizeLength),
280 ReceiveName(SizeLength),
283 ULeb128(u32),
286 ILeb128(u32),
289 ByteList(SizeLength),
292 ByteArray(u32),
294 TaggedEnum(BTreeMap<u8, (String, Fields)>),
296}
297
298impl Type {
299 #[doc(hidden)]
300 pub fn set_size_length(self, size_len: SizeLength) -> Type {
303 match self {
304 Type::List(_, ty) => Type::List(size_len, ty),
305 Type::Set(_, ty) => Type::Set(size_len, ty),
306 Type::Map(_, key_ty, val_ty) => Type::Map(size_len, key_ty, val_ty),
307 Type::String(_) => Type::String(size_len),
308 Type::ByteList(_) => Type::ByteList(size_len),
309 t => t,
310 }
311 }
312}
313
314impl SchemaType for () {
315 fn get_type() -> Type { Type::Unit }
316}
317impl SchemaType for bool {
318 fn get_type() -> Type { Type::Bool }
319}
320impl SchemaType for u8 {
321 fn get_type() -> Type { Type::U8 }
322}
323impl SchemaType for u16 {
324 fn get_type() -> Type { Type::U16 }
325}
326impl SchemaType for u32 {
327 fn get_type() -> Type { Type::U32 }
328}
329impl SchemaType for u64 {
330 fn get_type() -> Type { Type::U64 }
331}
332impl SchemaType for u128 {
333 fn get_type() -> Type { Type::U128 }
334}
335impl SchemaType for i8 {
336 fn get_type() -> Type { Type::I8 }
337}
338impl SchemaType for i16 {
339 fn get_type() -> Type { Type::I16 }
340}
341impl SchemaType for i32 {
342 fn get_type() -> Type { Type::I32 }
343}
344impl SchemaType for i64 {
345 fn get_type() -> Type { Type::I64 }
346}
347impl SchemaType for i128 {
348 fn get_type() -> Type { Type::I128 }
349}
350impl SchemaType for Amount {
351 fn get_type() -> Type { Type::Amount }
352}
353impl SchemaType for ModuleReference {
354 fn get_type() -> Type { Type::ByteArray(32) }
355}
356impl SchemaType for AccountAddress {
357 fn get_type() -> Type { Type::AccountAddress }
358}
359impl SchemaType for ContractAddress {
360 fn get_type() -> Type { Type::ContractAddress }
361}
362impl SchemaType for Address {
363 fn get_type() -> Type {
364 Type::Enum(Vec::from([
365 (String::from("Account"), Fields::Unnamed(Vec::from([Type::AccountAddress]))),
366 (String::from("Contract"), Fields::Unnamed(Vec::from([Type::ContractAddress]))),
367 ]))
368 }
369}
370impl SchemaType for Timestamp {
371 fn get_type() -> Type { Type::Timestamp }
372}
373impl SchemaType for Duration {
374 fn get_type() -> Type { Type::Duration }
375}
376impl<T: SchemaType> SchemaType for Option<T> {
377 fn get_type() -> Type {
378 Type::Enum(Vec::from([
379 (String::from("None"), Fields::None),
380 (String::from("Some"), Fields::Unnamed(Vec::from([T::get_type()]))),
381 ]))
382 }
383}
384impl<L: SchemaType, R: SchemaType> SchemaType for (L, R) {
385 fn get_type() -> Type { Type::Pair(Box::new(L::get_type()), Box::new(R::get_type())) }
386}
387impl<T: SchemaType> SchemaType for Vec<T> {
388 fn get_type() -> Type { Type::List(SizeLength::U32, Box::new(T::get_type())) }
389}
390impl<T: SchemaType> SchemaType for BTreeSet<T> {
391 fn get_type() -> Type { Type::Set(SizeLength::U32, Box::new(T::get_type())) }
392}
393impl<K: SchemaType, V: SchemaType> SchemaType for BTreeMap<K, V> {
394 fn get_type() -> Type {
395 Type::Map(SizeLength::U32, Box::new(K::get_type()), Box::new(V::get_type()))
396 }
397}
398impl<T: SchemaType> SchemaType for HashSet<T> {
399 fn get_type() -> Type { Type::Set(SizeLength::U32, Box::new(T::get_type())) }
400}
401impl<K: SchemaType, V: SchemaType> SchemaType for HashMap<K, V> {
402 fn get_type() -> Type {
403 Type::Map(SizeLength::U32, Box::new(K::get_type()), Box::new(V::get_type()))
404 }
405}
406impl SchemaType for [u8] {
407 fn get_type() -> Type { Type::ByteList(SizeLength::U32) }
408}
409
410impl SchemaType for String {
411 fn get_type() -> Type { Type::String(SizeLength::U32) }
412}
413
414impl SchemaType for &str {
415 fn get_type() -> Type { String::get_type() }
416}
417
418impl SchemaType for OwnedContractName {
419 fn get_type() -> Type { Type::ContractName(SizeLength::U16) }
420}
421
422impl SchemaType for OwnedReceiveName {
423 fn get_type() -> Type { Type::ReceiveName(SizeLength::U16) }
424}
425
426impl SchemaType for OwnedEntrypointName {
427 fn get_type() -> Type { Type::String(SizeLength::U16) }
428}
429
430impl SchemaType for OwnedParameter {
431 fn get_type() -> Type { Type::ByteList(SizeLength::U16) }
432}
433
434impl<A: SchemaType, const N: usize> SchemaType for [A; N] {
435 fn get_type() -> Type { Type::Array(N.try_into().unwrap(), Box::new(A::get_type())) }
436}
437
438impl<Kind> SchemaType for NonZeroThresholdU8<Kind> {
439 fn get_type() -> Type { u8::get_type() }
442}
443
444impl Serial for Fields {
445 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
446 match self {
447 Fields::Named(fields) => {
448 out.write_u8(0)?;
449 fields.serial(out)?;
450 }
451 Fields::Unnamed(fields) => {
452 out.write_u8(1)?;
453 fields.serial(out)?;
454 }
455 Fields::None => {
456 out.write_u8(2)?;
457 }
458 }
459 Ok(())
460 }
461}
462
463impl Deserial for Fields {
464 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
465 let idx = source.read_u8()?;
466 match idx {
467 0 => Ok(Fields::Named(source.get()?)),
468 1 => Ok(Fields::Unnamed(source.get()?)),
469 2 => Ok(Fields::None),
470 _ => Err(ParseError::default()),
471 }
472 }
473}
474
475impl Serial for ModuleV0 {
476 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
477 self.contracts.serial(out)?;
478 Ok(())
479 }
480}
481
482impl Serial for ModuleV1 {
483 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
484 self.contracts.serial(out)?;
485 Ok(())
486 }
487}
488
489impl Serial for ModuleV2 {
490 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
491 self.contracts.serial(out)?;
492 Ok(())
493 }
494}
495
496impl Serial for ModuleV3 {
497 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
498 self.contracts.serial(out)?;
499 Ok(())
500 }
501}
502
503impl Serial for VersionedModuleSchema {
504 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
505 out.write_u16(u16::MAX)?;
507 match self {
508 VersionedModuleSchema::V0(module) => {
509 out.write_u8(0)?;
510 module.serial(out)?;
511 }
512 VersionedModuleSchema::V1(module) => {
513 out.write_u8(1)?;
514 module.serial(out)?;
515 }
516 VersionedModuleSchema::V2(module) => {
517 out.write_u8(2)?;
518 module.serial(out)?;
519 }
520 VersionedModuleSchema::V3(module) => {
521 out.write_u8(3)?;
522 module.serial(out)?;
523 }
524 }
525 Ok(())
526 }
527}
528
529impl Deserial for ModuleV0 {
530 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
531 let len: u32 = source.get()?;
532 let contracts = deserial_map_no_length_no_order_check(source, len as usize)?;
533 Ok(ModuleV0 {
534 contracts,
535 })
536 }
537}
538
539impl Deserial for ModuleV1 {
540 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
541 let len: u32 = source.get()?;
542 let contracts = deserial_map_no_length_no_order_check(source, len as usize)?;
543 Ok(ModuleV1 {
544 contracts,
545 })
546 }
547}
548
549impl Deserial for ModuleV2 {
550 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
551 let len: u32 = source.get()?;
552 let contracts = deserial_map_no_length_no_order_check(source, len as usize)?;
553 Ok(ModuleV2 {
554 contracts,
555 })
556 }
557}
558
559impl Deserial for ModuleV3 {
560 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
561 let len: u32 = source.get()?;
562 let contracts = deserial_map_no_length_no_order_check(source, len as usize)?;
563 Ok(ModuleV3 {
564 contracts,
565 })
566 }
567}
568
569impl Deserial for VersionedModuleSchema {
570 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
571 let prefix = source.read_u16()?;
573 if prefix != u16::MAX {
574 return Err(ParseError {});
575 }
576 let version = source.read_u8()?;
577 match version {
578 0 => {
579 let module = source.get()?;
580 Ok(VersionedModuleSchema::V0(module))
581 }
582 1 => {
583 let module = source.get()?;
584 Ok(VersionedModuleSchema::V1(module))
585 }
586 2 => {
587 let module = source.get()?;
588 Ok(VersionedModuleSchema::V2(module))
589 }
590 3 => {
591 let module = source.get()?;
592 Ok(VersionedModuleSchema::V3(module))
593 }
594 _ => Err(ParseError {}),
595 }
596 }
597}
598
599impl Serial for ContractV0 {
600 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
601 self.state.serial(out)?;
602 self.init.serial(out)?;
603 self.receive.serial(out)?;
604 Ok(())
605 }
606}
607
608impl Serial for ContractV1 {
609 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
610 self.init.serial(out)?;
611 self.receive.serial(out)?;
612 Ok(())
613 }
614}
615
616impl Serial for ContractV2 {
617 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
618 self.init.serial(out)?;
619 self.receive.serial(out)?;
620 Ok(())
621 }
622}
623
624impl Serial for ContractV3 {
625 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
626 self.init.serial(out)?;
627 self.receive.serial(out)?;
628 self.event.serial(out)?;
629 Ok(())
630 }
631}
632
633impl Deserial for ContractV0 {
634 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
635 let state = source.get()?;
636 let init = source.get()?;
637 let len: u32 = source.get()?;
638 let receive = deserial_map_no_length_no_order_check(source, len as usize)?;
639 Ok(ContractV0 {
640 state,
641 init,
642 receive,
643 })
644 }
645}
646
647impl Deserial for ContractV1 {
648 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
649 let init = source.get()?;
650 let len: u32 = source.get()?;
651 let receive = deserial_map_no_length_no_order_check(source, len as usize)?;
652 Ok(ContractV1 {
653 init,
654 receive,
655 })
656 }
657}
658
659impl Deserial for ContractV2 {
660 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
661 let init = source.get()?;
662 let len: u32 = source.get()?;
663 let receive = deserial_map_no_length_no_order_check(source, len as usize)?;
664 Ok(ContractV2 {
665 init,
666 receive,
667 })
668 }
669}
670
671impl Deserial for ContractV3 {
672 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
673 let init = source.get()?;
674 let len: u32 = source.get()?;
675 let receive = deserial_map_no_length_no_order_check(source, len as usize)?;
676 let event = source.get()?;
677 Ok(ContractV3 {
678 init,
679 receive,
680 event,
681 })
682 }
683}
684
685impl Serial for FunctionV1 {
686 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
687 match self {
688 FunctionV1::Parameter(parameter) => {
689 out.write_u8(0)?;
690 parameter.serial(out)
691 }
692 FunctionV1::ReturnValue(return_value) => {
693 out.write_u8(1)?;
694 return_value.serial(out)
695 }
696 FunctionV1::Both {
697 parameter,
698 return_value,
699 } => {
700 out.write_u8(2)?;
701 parameter.serial(out)?;
702 return_value.serial(out)
703 }
704 }
705 }
706}
707
708impl Deserial for FunctionV1 {
709 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
710 let idx = source.read_u8()?;
711 match idx {
712 0 => Ok(FunctionV1::Parameter(source.get()?)),
713 1 => Ok(FunctionV1::ReturnValue(source.get()?)),
714 2 => Ok(FunctionV1::Both {
715 parameter: source.get()?,
716 return_value: source.get()?,
717 }),
718 _ => Err(ParseError::default()),
719 }
720 }
721}
722
723impl Serial for FunctionV2 {
724 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
725 let parameter = self.parameter.is_some();
726 let return_value = self.return_value.is_some();
727 let error = self.error.is_some();
728 let tag: u8 = match (parameter, return_value, error) {
729 (true, false, false) => 0,
731 (false, true, false) => 1,
733 (true, true, false) => 2,
735 (false, false, true) => 3,
737 (true, false, true) => 4,
739 (false, true, true) => 5,
741 (true, true, true) => 6,
743 (false, false, false) => 7,
745 };
746 out.write_u8(tag)?;
747 if let Some(p) = self.parameter.as_ref() {
748 p.serial(out)?;
749 }
750 if let Some(rv) = self.return_value.as_ref() {
751 rv.serial(out)?;
752 }
753 if let Some(err) = self.error.as_ref() {
754 err.serial(out)?;
755 }
756 Ok(())
757 }
758}
759
760impl Deserial for FunctionV2 {
761 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
762 let idx = source.read_u8()?;
763 let mut r = FunctionV2 {
764 parameter: None,
765 return_value: None,
766 error: None,
767 };
768 if idx > 7 {
769 return Err(ParseError::default());
770 }
771 if matches!(idx, 0 | 2 | 4 | 6) {
772 let _ = r.parameter.insert(source.get()?);
773 }
774 if matches!(idx, 1 | 2 | 5 | 6) {
775 let _ = r.return_value.insert(source.get()?);
776 }
777 if matches!(idx, 3..=6) {
778 let _ = r.error.insert(source.get()?);
779 }
780 Ok(r)
781 }
782}
783
784impl Serial for SizeLength {
785 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
786 match self {
787 SizeLength::U8 => out.write_u8(0)?,
788 SizeLength::U16 => out.write_u8(1)?,
789 SizeLength::U32 => out.write_u8(2)?,
790 SizeLength::U64 => out.write_u8(3)?,
791 }
792 Ok(())
793 }
794}
795
796impl Deserial for SizeLength {
797 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
798 let idx = source.read_u8()?;
799 match idx {
800 0 => Ok(SizeLength::U8),
801 1 => Ok(SizeLength::U16),
802 2 => Ok(SizeLength::U32),
803 3 => Ok(SizeLength::U64),
804 _ => Err(ParseError::default()),
805 }
806 }
807}
808
809impl Serial for Type {
810 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
811 match self {
812 Type::Unit => out.write_u8(0),
813 Type::Bool => out.write_u8(1),
814 Type::U8 => out.write_u8(2),
815 Type::U16 => out.write_u8(3),
816 Type::U32 => out.write_u8(4),
817 Type::U64 => out.write_u8(5),
818 Type::I8 => out.write_u8(6),
819 Type::I16 => out.write_u8(7),
820 Type::I32 => out.write_u8(8),
821 Type::I64 => out.write_u8(9),
822 Type::Amount => out.write_u8(10),
823 Type::AccountAddress => out.write_u8(11),
824 Type::ContractAddress => out.write_u8(12),
825 Type::Timestamp => out.write_u8(13),
826 Type::Duration => out.write_u8(14),
827 Type::Pair(left, right) => {
828 out.write_u8(15)?;
829 left.serial(out)?;
830 right.serial(out)
831 }
832 Type::List(len_size, ty) => {
833 out.write_u8(16)?;
834 len_size.serial(out)?;
835 ty.serial(out)
836 }
837 Type::Set(len_size, ty) => {
838 out.write_u8(17)?;
839 len_size.serial(out)?;
840 ty.serial(out)
841 }
842 Type::Map(len_size, key, value) => {
843 out.write_u8(18)?;
844 len_size.serial(out)?;
845 key.serial(out)?;
846 value.serial(out)
847 }
848 Type::Array(len, ty) => {
849 out.write_u8(19)?;
850 len.serial(out)?;
851 ty.serial(out)
852 }
853 Type::Struct(fields) => {
854 out.write_u8(20)?;
855 fields.serial(out)
856 }
857 Type::Enum(fields) => {
858 out.write_u8(21)?;
859 fields.serial(out)
860 }
861 Type::String(len) => {
862 out.write_u8(22)?;
863 len.serial(out)
864 }
865 Type::U128 => out.write_u8(23),
866 Type::I128 => out.write_u8(24),
867 Type::ContractName(len_size) => {
868 out.write_u8(25)?;
869 len_size.serial(out)
870 }
871 Type::ReceiveName(len_size) => {
872 out.write_u8(26)?;
873 len_size.serial(out)
874 }
875 Type::ULeb128(constraint) => {
876 out.write_u8(27)?;
877 constraint.serial(out)
878 }
879 Type::ILeb128(constraint) => {
880 out.write_u8(28)?;
881 constraint.serial(out)
882 }
883 Type::ByteList(len_size) => {
884 out.write_u8(29)?;
885 len_size.serial(out)
886 }
887 Type::ByteArray(len) => {
888 out.write_u8(30)?;
889 len.serial(out)
890 }
891 Type::TaggedEnum(fields) => {
892 out.write_u8(31)?;
893 fields.serial(out)
894 }
895 }
896 }
897}
898
899impl Deserial for Type {
900 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
901 let idx = source.read_u8()?;
902 match idx {
903 0 => Ok(Type::Unit),
904 1 => Ok(Type::Bool),
905 2 => Ok(Type::U8),
906 3 => Ok(Type::U16),
907 4 => Ok(Type::U32),
908 5 => Ok(Type::U64),
909 6 => Ok(Type::I8),
910 7 => Ok(Type::I16),
911 8 => Ok(Type::I32),
912 9 => Ok(Type::I64),
913 10 => Ok(Type::Amount),
914 11 => Ok(Type::AccountAddress),
915 12 => Ok(Type::ContractAddress),
916 13 => Ok(Type::Timestamp),
917 14 => Ok(Type::Duration),
918 15 => {
919 let left = Type::deserial(source)?;
920 let right = Type::deserial(source)?;
921 Ok(Type::Pair(Box::new(left), Box::new(right)))
922 }
923 16 => {
924 let len_size = SizeLength::deserial(source)?;
925 let ty = Type::deserial(source)?;
926 Ok(Type::List(len_size, Box::new(ty)))
927 }
928 17 => {
929 let len_size = SizeLength::deserial(source)?;
930 let ty = Type::deserial(source)?;
931 Ok(Type::Set(len_size, Box::new(ty)))
932 }
933 18 => {
934 let len_size = SizeLength::deserial(source)?;
935 let key = Type::deserial(source)?;
936 let value = Type::deserial(source)?;
937 Ok(Type::Map(len_size, Box::new(key), Box::new(value)))
938 }
939 19 => {
940 let len = u32::deserial(source)?;
941 let ty = Type::deserial(source)?;
942 Ok(Type::Array(len, Box::new(ty)))
943 }
944 20 => {
945 let fields = source.get()?;
946 Ok(Type::Struct(fields))
947 }
948 21 => {
949 let variants = source.get()?;
950 Ok(Type::Enum(variants))
951 }
952 22 => {
953 let len_size = SizeLength::deserial(source)?;
954 Ok(Type::String(len_size))
955 }
956 23 => Ok(Type::U128),
957 24 => Ok(Type::I128),
958 25 => {
959 let len_size = SizeLength::deserial(source)?;
960 Ok(Type::ContractName(len_size))
961 }
962 26 => {
963 let len_size = SizeLength::deserial(source)?;
964 Ok(Type::ReceiveName(len_size))
965 }
966 27 => {
967 let constraint = u32::deserial(source)?;
968 Ok(Type::ULeb128(constraint))
969 }
970 28 => {
971 let constraint = u32::deserial(source)?;
972 Ok(Type::ILeb128(constraint))
973 }
974 29 => {
975 let len_size = SizeLength::deserial(source)?;
976 Ok(Type::ByteList(len_size))
977 }
978 30 => {
979 let len = u32::deserial(source)?;
980 Ok(Type::ByteArray(len))
981 }
982 31 => {
983 let variants = source.get()?;
984 Ok(Type::TaggedEnum(variants))
985 }
986
987 _ => Err(ParseError::default()),
988 }
989 }
990}
991
992impl From<TryFromIntError> for ParseError {
993 fn from(_: TryFromIntError) -> Self { ParseError::default() }
994}
995
996pub fn serial_length<W: Write>(
998 len: usize,
999 size_len: SizeLength,
1000 out: &mut W,
1001) -> Result<(), W::Err> {
1002 let to_w_err = |_| W::Err::default();
1003 match size_len {
1004 SizeLength::U8 => u8::try_from(len).map_err(to_w_err)?.serial(out)?,
1005 SizeLength::U16 => u16::try_from(len).map_err(to_w_err)?.serial(out)?,
1006 SizeLength::U32 => u32::try_from(len).map_err(to_w_err)?.serial(out)?,
1007 SizeLength::U64 => u64::try_from(len).map_err(to_w_err)?.serial(out)?,
1008 }
1009 Ok(())
1010}
1011
1012pub fn deserial_length(source: &mut impl Read, size_len: SizeLength) -> ParseResult<usize> {
1014 let len: usize = match size_len {
1015 SizeLength::U8 => u8::deserial(source)?.into(),
1016 SizeLength::U16 => u16::deserial(source)?.into(),
1017 SizeLength::U32 => u32::deserial(source)?.try_into()?,
1018 SizeLength::U64 => u64::deserial(source)?.try_into()?,
1019 };
1020 Ok(len)
1021}
1022
1023#[cfg(feature = "derive-serde")]
1025mod impls {
1026 use crate::{from_bytes, schema::*};
1027 use base64::{engine::general_purpose, Engine};
1028
1029 enum VersionedContractSchema {
1032 V0(ContractV0),
1033 V1(ContractV1),
1034 V2(ContractV2),
1035 V3(ContractV3),
1036 }
1037
1038 #[derive(Debug, thiserror::Error, Clone, Copy)]
1039 pub enum VersionedSchemaError {
1040 #[error("Parse error")]
1041 ParseError,
1042 #[error("Missing Schema Version")]
1043 MissingSchemaVersion,
1044 #[error("Invalid Schema Version")]
1045 InvalidSchemaVersion,
1046 #[error("Unable to find contract schema in module schema")]
1047 NoContractInModule,
1048 #[error("Receive function schema not found in contract schema")]
1049 NoReceiveInContract,
1050 #[error("Init function schema not found in contract schema")]
1051 NoInitInContract,
1052 #[error("Receive function schema does not contain a parameter schema")]
1053 NoParamsInReceive,
1054 #[error("Init function schema does not contain a parameter schema")]
1055 NoParamsInInit,
1056 #[error("Receive function schema not found in contract schema")]
1057 NoErrorInReceive,
1058 #[error("Init function schema does not contain an error schema")]
1059 NoErrorInInit,
1060 #[error("Errors not supported for this module version")]
1061 ErrorNotSupported,
1062 #[error("Receive function schema has no return value schema")]
1063 NoReturnValueInReceive,
1064 #[error("Return values not supported for this module version")]
1065 ReturnValueNotSupported,
1066 #[error("Event schema not found in contract schema")]
1067 NoEventInContract,
1068 #[error("Events not supported for this module version")]
1069 EventNotSupported,
1070 }
1071
1072 impl From<ParseError> for VersionedSchemaError {
1073 fn from(_: ParseError) -> Self { VersionedSchemaError::ParseError }
1074 }
1075
1076 fn get_versioned_contract_schema(
1078 versioned_module_schema: &VersionedModuleSchema,
1079 contract_name: &str,
1080 ) -> Result<VersionedContractSchema, VersionedSchemaError> {
1081 let versioned_contract_schema: VersionedContractSchema = match versioned_module_schema {
1082 VersionedModuleSchema::V0(module_schema) => {
1083 let contract_schema = module_schema
1084 .contracts
1085 .get(contract_name)
1086 .ok_or(VersionedSchemaError::NoContractInModule)?
1087 .clone();
1088 VersionedContractSchema::V0(contract_schema)
1089 }
1090 VersionedModuleSchema::V1(module_schema) => {
1091 let contract_schema = module_schema
1092 .contracts
1093 .get(contract_name)
1094 .ok_or(VersionedSchemaError::NoContractInModule)?
1095 .clone();
1096 VersionedContractSchema::V1(contract_schema)
1097 }
1098 VersionedModuleSchema::V2(module_schema) => {
1099 let contract_schema = module_schema
1100 .contracts
1101 .get(contract_name)
1102 .ok_or(VersionedSchemaError::NoContractInModule)?
1103 .clone();
1104 VersionedContractSchema::V2(contract_schema)
1105 }
1106 VersionedModuleSchema::V3(module_schema) => {
1107 let contract_schema = module_schema
1108 .contracts
1109 .get(contract_name)
1110 .ok_or(VersionedSchemaError::NoContractInModule)?
1111 .clone();
1112 VersionedContractSchema::V3(contract_schema)
1113 }
1114 };
1115
1116 Ok(versioned_contract_schema)
1117 }
1118
1119 impl VersionedModuleSchema {
1120 pub fn new(
1124 schema_bytes: &[u8],
1125 schema_version: &Option<u8>,
1126 ) -> Result<Self, VersionedSchemaError> {
1127 let versioned_module_schema = match from_bytes::<VersionedModuleSchema>(schema_bytes) {
1128 Ok(versioned) => versioned,
1129 Err(_) => match schema_version {
1130 Some(0) => VersionedModuleSchema::V0(from_bytes(schema_bytes)?),
1131 Some(1) => VersionedModuleSchema::V1(from_bytes(schema_bytes)?),
1132 Some(2) => VersionedModuleSchema::V2(from_bytes(schema_bytes)?),
1133 Some(3) => VersionedModuleSchema::V3(from_bytes(schema_bytes)?),
1134 Some(_) => return Err(VersionedSchemaError::InvalidSchemaVersion),
1135 None => return Err(VersionedSchemaError::MissingSchemaVersion),
1136 },
1137 };
1138 Ok(versioned_module_schema)
1139 }
1140
1141 pub fn from_base64_str(s: &str) -> Result<Self, VersionedSchemaError> {
1143 let bytes: Vec<u8> = general_purpose::STANDARD_NO_PAD
1144 .decode(s)
1145 .map_err(|_| VersionedSchemaError::ParseError)?;
1146 let mut cursor = Cursor::new(bytes);
1147 let schema = VersionedModuleSchema::deserial(&mut cursor)?;
1148 Ok(schema)
1149 }
1150
1151 pub fn get_receive_param_schema(
1154 &self,
1155 contract_name: &str,
1156 function_name: &str,
1157 ) -> Result<Type, VersionedSchemaError> {
1158 let versioned_contract_schema = get_versioned_contract_schema(self, contract_name)?;
1159 let param_schema = match versioned_contract_schema {
1160 VersionedContractSchema::V0(contract_schema) => contract_schema
1161 .receive
1162 .get(function_name)
1163 .ok_or(VersionedSchemaError::NoReceiveInContract)?
1164 .clone(),
1165 VersionedContractSchema::V1(contract_schema) => contract_schema
1166 .receive
1167 .get(function_name)
1168 .ok_or(VersionedSchemaError::NoReceiveInContract)?
1169 .parameter()
1170 .ok_or(VersionedSchemaError::NoParamsInReceive)?
1171 .clone(),
1172 VersionedContractSchema::V2(contract_schema) => contract_schema
1173 .receive
1174 .get(function_name)
1175 .ok_or(VersionedSchemaError::NoReceiveInContract)?
1176 .parameter()
1177 .ok_or(VersionedSchemaError::NoParamsInReceive)?
1178 .clone(),
1179 VersionedContractSchema::V3(contract_schema) => contract_schema
1180 .receive
1181 .get(function_name)
1182 .ok_or(VersionedSchemaError::NoReceiveInContract)?
1183 .parameter()
1184 .ok_or(VersionedSchemaError::NoParamsInReceive)?
1185 .clone(),
1186 };
1187 Ok(param_schema)
1188 }
1189
1190 pub fn get_init_param_schema(
1193 &self,
1194 contract_name: &str,
1195 ) -> Result<Type, VersionedSchemaError> {
1196 let versioned_contract_schema = get_versioned_contract_schema(self, contract_name)?;
1197 let param_schema = match versioned_contract_schema {
1198 VersionedContractSchema::V0(contract_schema) => contract_schema
1199 .init
1200 .as_ref()
1201 .ok_or(VersionedSchemaError::NoInitInContract)?
1202 .clone(),
1203 VersionedContractSchema::V1(contract_schema) => contract_schema
1204 .init
1205 .as_ref()
1206 .ok_or(VersionedSchemaError::NoInitInContract)?
1207 .parameter()
1208 .ok_or(VersionedSchemaError::NoParamsInInit)?
1209 .clone(),
1210 VersionedContractSchema::V2(contract_schema) => contract_schema
1211 .init
1212 .as_ref()
1213 .ok_or(VersionedSchemaError::NoInitInContract)?
1214 .parameter()
1215 .ok_or(VersionedSchemaError::NoParamsInInit)?
1216 .clone(),
1217 VersionedContractSchema::V3(contract_schema) => contract_schema
1218 .init
1219 .as_ref()
1220 .ok_or(VersionedSchemaError::NoInitInContract)?
1221 .parameter()
1222 .ok_or(VersionedSchemaError::NoParamsInInit)?
1223 .clone(),
1224 };
1225 Ok(param_schema)
1226 }
1227
1228 pub fn get_event_schema(&self, contract_name: &str) -> Result<Type, VersionedSchemaError> {
1230 let versioned_contract_schema = get_versioned_contract_schema(self, contract_name)?;
1231
1232 match versioned_contract_schema {
1233 VersionedContractSchema::V0(_) => Err(VersionedSchemaError::EventNotSupported)?,
1234 VersionedContractSchema::V1(_) => Err(VersionedSchemaError::EventNotSupported)?,
1235 VersionedContractSchema::V2(_) => Err(VersionedSchemaError::EventNotSupported)?,
1236 VersionedContractSchema::V3(contract_schema) => {
1237 contract_schema.event.ok_or(VersionedSchemaError::NoEventInContract)
1238 }
1239 }
1240 }
1241
1242 pub fn get_receive_error_schema(
1245 &self,
1246 contract_name: &str,
1247 function_name: &str,
1248 ) -> Result<Type, VersionedSchemaError> {
1249 let versioned_contract_schema = get_versioned_contract_schema(self, contract_name)?;
1250 let param_schema = match versioned_contract_schema {
1251 VersionedContractSchema::V0(_) => {
1252 return Err(VersionedSchemaError::ErrorNotSupported)
1253 }
1254 VersionedContractSchema::V1(_) => {
1255 return Err(VersionedSchemaError::ErrorNotSupported)
1256 }
1257 VersionedContractSchema::V2(contract_schema) => contract_schema
1258 .receive
1259 .get(function_name)
1260 .ok_or(VersionedSchemaError::NoReceiveInContract)?
1261 .error()
1262 .ok_or(VersionedSchemaError::NoErrorInReceive)?
1263 .clone(),
1264 VersionedContractSchema::V3(contract_schema) => contract_schema
1265 .receive
1266 .get(function_name)
1267 .ok_or(VersionedSchemaError::NoReceiveInContract)?
1268 .error()
1269 .ok_or(VersionedSchemaError::NoErrorInReceive)?
1270 .clone(),
1271 };
1272 Ok(param_schema)
1273 }
1274
1275 pub fn get_init_error_schema(
1278 &self,
1279 contract_name: &str,
1280 ) -> Result<Type, VersionedSchemaError> {
1281 let versioned_contract_schema = get_versioned_contract_schema(self, contract_name)?;
1282 let param_schema = match versioned_contract_schema {
1283 VersionedContractSchema::V0(_) => {
1284 return Err(VersionedSchemaError::ErrorNotSupported)
1285 }
1286 VersionedContractSchema::V1(_) => {
1287 return Err(VersionedSchemaError::ErrorNotSupported)
1288 }
1289 VersionedContractSchema::V2(contract_schema) => contract_schema
1290 .init
1291 .as_ref()
1292 .ok_or(VersionedSchemaError::NoInitInContract)?
1293 .error()
1294 .ok_or(VersionedSchemaError::NoErrorInInit)?
1295 .clone(),
1296 VersionedContractSchema::V3(contract_schema) => contract_schema
1297 .init
1298 .as_ref()
1299 .ok_or(VersionedSchemaError::NoInitInContract)?
1300 .error()
1301 .ok_or(VersionedSchemaError::NoErrorInInit)?
1302 .clone(),
1303 };
1304 Ok(param_schema)
1305 }
1306
1307 pub fn get_receive_return_value_schema(
1309 &self,
1310 contract_name: &str,
1311 function_name: &str,
1312 ) -> Result<Type, VersionedSchemaError> {
1313 let versioned_contract_schema = get_versioned_contract_schema(self, contract_name)?;
1314 let return_value_schema = match versioned_contract_schema {
1315 VersionedContractSchema::V0(_) => {
1316 return Err(VersionedSchemaError::ReturnValueNotSupported)
1317 }
1318 VersionedContractSchema::V1(contract_schema) => contract_schema
1319 .receive
1320 .get(function_name)
1321 .ok_or(VersionedSchemaError::NoReceiveInContract)?
1322 .return_value()
1323 .ok_or(VersionedSchemaError::NoReturnValueInReceive)?
1324 .clone(),
1325 VersionedContractSchema::V2(contract_schema) => contract_schema
1326 .receive
1327 .get(function_name)
1328 .ok_or(VersionedSchemaError::NoReceiveInContract)?
1329 .return_value()
1330 .ok_or(VersionedSchemaError::NoReturnValueInReceive)?
1331 .clone(),
1332 VersionedContractSchema::V3(contract_schema) => contract_schema
1333 .receive
1334 .get(function_name)
1335 .ok_or(VersionedSchemaError::NoReceiveInContract)?
1336 .return_value()
1337 .ok_or(VersionedSchemaError::NoReturnValueInReceive)?
1338 .clone(),
1339 };
1340
1341 Ok(return_value_schema)
1342 }
1343 }
1344
1345 #[cfg(test)]
1346 mod tests {
1347 use super::*;
1348
1349 fn module_schema() -> VersionedModuleSchema {
1350 let module_bytes = hex::decode(
1351 "ffff02010000000c00000054657374436f6e7472616374010402030100000010000000726563656976655f66756e6374696f6e06060807",
1352 )
1353 .unwrap();
1354 VersionedModuleSchema::new(&module_bytes, &None).unwrap()
1355 }
1356
1357 #[test]
1358 fn test_getting_init_param_schema() {
1359 let extracted_type = module_schema().get_init_param_schema("TestContract").unwrap();
1360 assert_eq!(extracted_type, Type::U8)
1361 }
1362
1363 #[test]
1364 fn test_getting_get_event_schema() {
1365 let events = Type::Enum(vec![
1366 ("Foo".to_string(), Fields::None),
1367 ("Bar".to_string(), Fields::None),
1368 ]);
1369 let module_schema = VersionedModuleSchema::V3(ModuleV3 {
1370 contracts: BTreeMap::from([("TestContract".into(), ContractV3 {
1371 init: None,
1372 receive: BTreeMap::new(),
1373 event: Some(events.clone()),
1374 })]),
1375 });
1376 let extracted_type = module_schema.get_event_schema("TestContract").unwrap();
1377 assert_eq!(extracted_type, events)
1378 }
1379
1380 #[test]
1381 fn test_getting_receive_param_schema() {
1382 let extracted_type = module_schema()
1383 .get_receive_param_schema("TestContract", "receive_function")
1384 .unwrap();
1385 assert_eq!(extracted_type, Type::I8)
1386 }
1387
1388 #[test]
1389 fn test_getting_init_error_schema() {
1390 let extracted_type = module_schema().get_init_error_schema("TestContract").unwrap();
1391 assert_eq!(extracted_type, Type::U16)
1392 }
1393
1394 #[test]
1395 fn test_getting_receive_error_schema() {
1396 let extracted_type = module_schema()
1397 .get_receive_error_schema("TestContract", "receive_function")
1398 .unwrap();
1399 assert_eq!(extracted_type, Type::I16)
1400 }
1401
1402 #[test]
1403 fn test_getting_receive_return_value_schema() {
1404 let extracted_type = module_schema()
1405 .get_receive_return_value_schema("TestContract", "receive_function")
1406 .unwrap();
1407 assert_eq!(extracted_type, Type::I32)
1408 }
1409 }
1410}
1411
1412#[cfg(test)]
1413mod tests {
1414 use super::*;
1415 use arbitrary::*;
1416
1417 #[test]
1418 fn test_schema_serial_deserial_is_id() {
1419 use rand::prelude::*;
1420 use rand_pcg::Pcg64;
1421
1422 let seed: u64 = random();
1423 let mut rng = Pcg64::seed_from_u64(seed);
1424 let mut data = [0u8; 100000];
1425 rng.fill_bytes(&mut data);
1426
1427 let mut unstructured = Unstructured::new(&data);
1428
1429 for _ in 0..10000 {
1430 let schema = Type::arbitrary(&mut unstructured).unwrap();
1431
1432 let res = from_bytes::<Type>(&to_bytes(&schema)).unwrap();
1433 assert_eq!(schema, res);
1434 }
1435 }
1436
1437 fn serial_deserial<T: Serialize>(t: &T) -> ParseResult<T> { from_bytes::<T>(&to_bytes(t)) }
1439
1440 #[test]
1441 fn test_function_v1_serial_deserial_is_id() {
1442 let f1 = FunctionV1::Parameter(Type::String(SizeLength::U32));
1443 let f2 = FunctionV1::ReturnValue(Type::U128);
1444 let f3 = FunctionV1::Both {
1445 parameter: Type::Set(SizeLength::U8, Box::new(Type::ByteArray(10))),
1446 return_value: Type::ILeb128(3),
1447 };
1448
1449 assert_eq!(serial_deserial(&f1), Ok(f1));
1450 assert_eq!(serial_deserial(&f2), Ok(f2));
1451 assert_eq!(serial_deserial(&f3), Ok(f3));
1452 }
1453
1454 #[test]
1455 fn test_function_v2_serial_deserial_is_id() {
1456 let f1 = FunctionV2 {
1457 parameter: Some(Type::String(SizeLength::U32)),
1458 return_value: Some(Type::String(SizeLength::U32)),
1459 error: Some(Type::String(SizeLength::U32)),
1460 };
1461
1462 assert_eq!(serial_deserial(&f1), Ok(f1));
1463 }
1464
1465 #[test]
1466 fn test_module_v0_serial_deserial_is_id() {
1467 let m = ModuleV0 {
1468 contracts: BTreeMap::from([("a".into(), ContractV0 {
1469 init: Some(Type::U8),
1470 receive: BTreeMap::from([
1471 ("b".into(), Type::String(SizeLength::U32)),
1472 ("c".into(), Type::Bool),
1473 ]),
1474 state: Some(Type::String(SizeLength::U64)),
1475 })]),
1476 };
1477
1478 assert_eq!(serial_deserial(&m), Ok(m));
1479 }
1480
1481 #[test]
1482 fn test_module_v1_serial_deserial_is_id() {
1483 let m = ModuleV1 {
1484 contracts: BTreeMap::from([("a".into(), ContractV1 {
1485 init: Some(FunctionV1::Parameter(Type::U8)),
1486 receive: BTreeMap::from([
1487 ("b".into(), FunctionV1::ReturnValue(Type::String(SizeLength::U32))),
1488 ("c".into(), FunctionV1::Both {
1489 parameter: Type::U8,
1490 return_value: Type::Bool,
1491 }),
1492 ]),
1493 })]),
1494 };
1495
1496 assert_eq!(serial_deserial(&m), Ok(m));
1497 }
1498
1499 #[test]
1500 fn test_module_v2_serial_deserial_is_id() {
1501 let m = ModuleV2 {
1502 contracts: BTreeMap::from([("a".into(), ContractV2 {
1503 init: Some(FunctionV2 {
1504 parameter: Some(Type::String(SizeLength::U32)),
1505 return_value: Some(Type::String(SizeLength::U32)),
1506 error: Some(Type::String(SizeLength::U32)),
1507 }),
1508 receive: BTreeMap::from([
1509 ("b".into(), FunctionV2 {
1510 parameter: Some(Type::String(SizeLength::U32)),
1511 return_value: Some(Type::String(SizeLength::U32)),
1512 error: Some(Type::String(SizeLength::U32)),
1513 }),
1514 ("c".into(), FunctionV2 {
1515 parameter: Some(Type::String(SizeLength::U32)),
1516 return_value: Some(Type::String(SizeLength::U32)),
1517 error: Some(Type::String(SizeLength::U32)),
1518 }),
1519 ]),
1520 })]),
1521 };
1522
1523 assert_eq!(serial_deserial(&m), Ok(m));
1524 }
1525
1526 #[test]
1527 fn test_module_v3_schema_serial_deserial_is_id() {
1528 use rand::prelude::*;
1529 use rand_pcg::Pcg64;
1530
1531 let seed: u64 = random();
1532 let mut rng = Pcg64::seed_from_u64(seed);
1533 let mut data = [0u8; 100000];
1534 rng.fill_bytes(&mut data);
1535
1536 let mut unstructured = Unstructured::new(&data);
1537
1538 for _ in 0..10000 {
1539 let schema = ModuleV3::arbitrary(&mut unstructured).unwrap();
1540
1541 let res = from_bytes::<ModuleV3>(&to_bytes(&schema)).unwrap();
1542 assert_eq!(schema, res);
1543 }
1544 }
1545}