tezos_smart_rollup_installer_config/binary/
bin.rs1use tezos_data_encoding::enc::{
7 field, put_byte, put_bytes, BinError, BinResult, BinWriter,
8};
9use tezos_smart_rollup_host::path::Path;
10
11use crate::binary::SetInstruction;
12
13use super::{
14 instr::{ConfigInstruction, MoveInstruction, RefBytes, RevealInstruction},
15 owned::OwnedConfigProgram,
16};
17
18fn put_le_size(size: usize, out: &mut Vec<u8>) -> BinResult {
19 let size = u32::try_from(size).map_err(|_| {
20 BinError::custom(format!(
21 "Expected {} but got {}",
22 (u32::MAX >> 2) as usize,
23 size
24 ))
25 })?;
26 tezos_data_encoding::enc::put_bytes(&size.to_le_bytes(), out);
27 Ok(())
28}
29
30fn path_dynamic(p: &impl Path, output: &mut Vec<u8>) -> BinResult {
32 let data = p.as_bytes();
33 let size = data.len() as u8;
35 put_byte(&size, output);
36 put_bytes(data, output);
37 Ok(())
38}
39
40fn bytes_dynamic(b: &impl AsRef<[u8]>, output: &mut Vec<u8>) -> BinResult {
41 put_le_size(b.as_ref().len(), output)?;
42 put_bytes(b.as_ref(), output);
43 Ok(())
44}
45
46impl<'a> BinWriter for RefBytes<'a> {
47 fn bin_write(&self, output: &mut Vec<u8>) -> BinResult {
48 bytes_dynamic(self, output)
49 }
50}
51
52impl<P: Path> BinWriter for MoveInstruction<P> {
53 fn bin_write(&self, out: &mut Vec<u8>) -> tezos_data_encoding::enc::BinResult {
54 (|data: &Self, out: &mut Vec<u8>| {
55 tezos_data_encoding::enc::field("MoveInstruction::from", path_dynamic)(
56 &data.from, out,
57 )?;
58 tezos_data_encoding::enc::field("MoveInstruction::to", path_dynamic)(
59 &data.to, out,
60 )?;
61 Ok(())
62 })(self, out)
63 }
64}
65
66impl<P: Path, B: AsRef<[u8]>> BinWriter for RevealInstruction<P, B> {
67 fn bin_write(&self, out: &mut Vec<u8>) -> tezos_data_encoding::enc::BinResult {
68 (|data: &Self, out: &mut Vec<u8>| {
69 field("RevealInstruction::hash", bytes_dynamic)(&data.hash, out)?;
70 field("RevealInstruction::to", path_dynamic)(&data.to, out)?;
71 Ok(())
72 })(self, out)
73 }
74}
75
76impl<P: Path, B: AsRef<[u8]>> BinWriter for SetInstruction<P, B> {
77 fn bin_write(&self, out: &mut Vec<u8>) -> tezos_data_encoding::enc::BinResult {
78 (|data: &Self, out: &mut Vec<u8>| {
79 field("SetInstruction::value", bytes_dynamic)(&data.value, out)?;
80 field("SetInstruction::to", path_dynamic)(&data.to, out)?;
81 Ok(())
82 })(self, out)
83 }
84}
85
86impl<P: Path, B: AsRef<[u8]>> BinWriter for ConfigInstruction<P, B> {
87 fn bin_write(&self, out: &mut Vec<u8>) -> tezos_data_encoding::enc::BinResult {
88 use tezos_data_encoding::enc::{u8, variant_with_field};
89 match self {
90 ConfigInstruction::Reveal(inner) => variant_with_field(
91 "ConfigInstruction::Reveal",
92 u8,
93 <RevealInstruction<P, B> as BinWriter>::bin_write,
94 )(&0, inner, out),
95 ConfigInstruction::Move(inner) => {
96 tezos_data_encoding::enc::variant_with_field(
97 "ConfigInstruction::Move",
98 u8,
99 <MoveInstruction<P> as BinWriter>::bin_write,
100 )(&1, inner, out)
101 }
102 ConfigInstruction::Set(inner) => variant_with_field(
103 "ConfigInstruction::Set",
104 u8,
105 <SetInstruction<P, B> as BinWriter>::bin_write,
106 )(&2, inner, out),
107 }
108 }
109}
110
111impl BinWriter for OwnedConfigProgram {
115 fn bin_write(&self, output: &mut Vec<u8>) -> BinResult {
116 let initial_size = output.len();
117 for i in 0..self.0.len() {
118 let mut current_instr = vec![];
119 self.0[i].bin_write(&mut current_instr)?;
120 put_le_size(current_instr.len(), output)?;
123 output.extend_from_slice(¤t_instr);
124 }
125 put_le_size(output.len() - initial_size, output)?;
126 Ok(())
127 }
128}
129
130#[cfg(feature = "alloc")]
131#[cfg(test)]
132mod test {
133 use std::fmt::Debug;
134
135 use tezos_data_encoding::enc::BinWriter;
136
137 use crate::binary::NomReader;
138
139 fn roundtrip<'a, T: Debug + PartialEq + Eq + BinWriter + NomReader<'a>>(
145 orig: &T,
146 out: &'a mut Vec<u8>,
147 ) {
148 orig.bin_write(out).unwrap();
149
150 let decoded = T::nom_read(out).unwrap();
151 assert!(decoded.0.is_empty());
152 assert_eq!(*orig, decoded.1);
153 }
154
155 #[test]
156 fn roundtrip_encdec() {
157 use tezos_smart_rollup_host::path::RefPath;
158
159 use crate::binary::instr::{
160 ConfigInstruction, MoveInstruction, RefBytes, RevealInstruction,
161 };
162 roundtrip(&RefBytes("hello".as_bytes()), &mut vec![]);
163
164 roundtrip(
165 &MoveInstruction {
166 from: RefPath::assert_from("/d".as_bytes()),
167 to: RefPath::assert_from("/cc".as_bytes()),
168 },
169 &mut vec![],
170 );
171
172 roundtrip(
173 &RevealInstruction {
174 to: RefPath::assert_from("/fldl/sfjisfkj".as_bytes()),
175 hash: RefBytes("some hash should be 33 bytes".as_bytes()),
176 },
177 &mut vec![],
178 );
179
180 roundtrip(
181 &ConfigInstruction::Reveal(RevealInstruction {
182 to: RefPath::assert_from("/fldl/sfjisfkj".as_bytes()),
183 hash: RefBytes("some hash should be 33 bytes".as_bytes()),
184 }),
185 &mut vec![],
186 );
187 }
188}