trn_pact/types/
contract.rs1use crate::types::DataTable;
20use alloc::vec::Vec;
21use bit_reverse::ParallelReverse;
22
23#[cfg_attr(feature = "std", derive(Debug, PartialEq))]
24pub enum BinaryFormatErr {
26 UnsupportedVersion,
28 MalformedDataTable(&'static str),
30 TooShort,
32}
33
34#[cfg_attr(feature = "std", derive(Debug, PartialEq))]
37pub struct Contract {
38 pub data_table: DataTable,
39 pub bytecode: Vec<u8>,
40}
41
42impl Contract {
43 pub fn encode(&self, buf: &mut Vec<u8>) {
45 buf.push(0); self.data_table.encode(buf);
47 buf.extend(self.bytecode.clone());
48 }
49 pub fn decode(buf: &Vec<u8>) -> Result<Self, BinaryFormatErr> {
51 if buf.len() < 2 {
52 return Err(BinaryFormatErr::TooShort);
53 }
54 if buf[0].swap_bits() != 0 {
55 return Err(BinaryFormatErr::UnsupportedVersion);
56 }
57 let (data_table, offset) = DataTable::decode(buf[1..].to_vec())
58 .map_err(|err| BinaryFormatErr::MalformedDataTable(err))?;
59 let bytecode = buf[1usize + offset..].to_vec();
60 Ok(Self {
61 data_table,
62 bytecode,
63 })
64 }
65}
66
67#[cfg(test)]
68mod test {
69 use super::*;
70 use crate::interpreter::{Comparator, Conjunction, OpCode, OpComp, OpConj, OpLoad};
71 use crate::types::{Numeric, PactType, StringLike};
72
73 #[test]
74 fn contract_binary_format_unsupported_version() {
75 assert_eq!(
76 Contract::decode([1, 0].to_vec().as_ref()),
77 Err(BinaryFormatErr::UnsupportedVersion)
78 );
79 }
80
81 #[test]
82 fn contract_binary_format_too_short() {
83 assert_eq!(
84 Contract::decode([0].to_vec().as_ref()),
85 Err(BinaryFormatErr::TooShort)
86 );
87 }
88
89 #[test]
90 fn contract_encode_1() {
91 let contract = Contract {
92 data_table: DataTable::new(vec![
93 PactType::Numeric(Numeric(10)),
94 PactType::Numeric(Numeric(20)),
95 ]),
96 bytecode: vec![OpCode::COMP(Comparator::new(OpComp::EQ)).into(), 0x00],
97 };
98 let mut encoded_payload = vec![];
99 contract.encode(&mut encoded_payload);
100 println!("{:?}", encoded_payload);
101 }
102
103 #[test]
104 fn contract_encode_2() {
105 let contract = Contract {
106 data_table: DataTable::new(vec![
107 PactType::Numeric(Numeric(10)),
108 PactType::StringLike(StringLike(b"hello, world".to_vec())),
109 ]),
110 bytecode: vec![
111 OpCode::COMP(Comparator::new(OpComp::EQ)).into(),
112 0x00,
113 OpCode::COMP(Comparator::new(OpComp::EQ)).into(),
114 0x11,
115 ],
116 };
117 let mut encoded_payload = vec![];
118 contract.encode(&mut encoded_payload);
119 println!("{:?}", encoded_payload);
120 }
121
122 #[test]
123 fn contract_encode_3() {
124 let contract = Contract {
125 data_table: DataTable::new(vec![
126 PactType::Numeric(Numeric(10)),
127 PactType::StringLike(StringLike(b"hello, world".to_vec())),
128 ]),
129 bytecode: vec![
130 OpCode::COMP(Comparator::new(OpComp::EQ).invert()).into(),
131 0x00,
132 OpCode::COMP(Comparator::new(OpComp::EQ).load(OpLoad::INPUT_VS_INPUT)).into(),
133 0x11,
134 ],
135 };
136 let mut encoded_payload = vec![];
137 contract.encode(&mut encoded_payload);
138 println!("{:?}", encoded_payload);
139 }
140
141 #[test]
142 fn contract_encode_4() {
143 let contract = Contract {
144 data_table: DataTable::new(vec![
145 PactType::Numeric(Numeric(10)),
146 PactType::Numeric(Numeric(20)),
147 ]),
148 bytecode: vec![
149 OpCode::COMP(Comparator::new(OpComp::EQ)).into(),
150 0x00,
151 OpCode::CONJ(Conjunction::new(OpConj::AND)).into(),
152 ],
153 };
154 let mut encoded_payload = vec![];
155 contract.encode(&mut encoded_payload);
156 println!("{:?}", encoded_payload);
157 }
158}