miden_core/mast/serialization/
mod.rs1use alloc::{
42 collections::BTreeMap,
43 string::{String, ToString},
44 sync::Arc,
45 vec::Vec,
46};
47
48use decorator::{DecoratorDataBuilder, DecoratorInfo};
49use string_table::StringTable;
50
51use super::{DecoratedOpLink, DecoratorId, MastForest, MastNode, MastNodeId};
52use crate::{
53 AdviceMap,
54 mast::{MastForestContributor, MastNodeBuilder},
55 utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
56};
57
58mod decorator;
59
60mod info;
61use info::MastNodeInfo;
62
63mod basic_blocks;
64use basic_blocks::{BasicBlockDataBuilder, BasicBlockDataDecoder};
65
66use crate::DecoratorList;
67
68mod string_table;
69
70#[cfg(test)]
71mod tests;
72
73type NodeDataOffset = u32;
78
79type DecoratorDataOffset = u32;
81
82type StringDataOffset = usize;
84
85type StringIndex = usize;
87
88const MAGIC: &[u8; 5] = b"MAST\0";
93
94const VERSION: [u8; 3] = [0, 0, 0];
100
101impl Serializable for MastForest {
105 fn write_into<W: ByteWriter>(&self, target: &mut W) {
106 let mut basic_block_data_builder = BasicBlockDataBuilder::new();
107
108 let mut before_enter_decorators: Vec<(usize, Vec<DecoratorId>)> = Vec::new();
110 let mut after_exit_decorators: Vec<(usize, Vec<DecoratorId>)> = Vec::new();
111
112 let mut basic_block_decorators: Vec<(usize, Vec<DecoratedOpLink>)> = Vec::new();
113
114 target.write_bytes(MAGIC);
116 target.write_bytes(&VERSION);
117
118 target.write_usize(self.nodes.len());
120 target.write_usize(self.debug_info.num_decorators());
121
122 let roots: Vec<u32> = self.roots.iter().copied().map(u32::from).collect();
124 roots.write_into(target);
125
126 let mast_node_infos: Vec<MastNodeInfo> = self
129 .nodes
130 .iter()
131 .enumerate()
132 .map(|(mast_node_id, mast_node)| {
133 let node_id = MastNodeId::new_unchecked(mast_node_id as u32);
134
135 let before_decorators = self.before_enter_decorators(node_id);
137 if !before_decorators.is_empty() {
138 before_enter_decorators.push((mast_node_id, before_decorators.to_vec()));
139 }
140
141 let after_decorators = self.after_exit_decorators(node_id);
142 if !after_decorators.is_empty() {
143 after_exit_decorators.push((mast_node_id, after_decorators.to_vec()));
144 }
145
146 let ops_offset = if let MastNode::Block(basic_block) = mast_node {
147 let ops_offset = basic_block_data_builder.encode_basic_block(basic_block);
148
149 basic_block_decorators
150 .push((mast_node_id, basic_block.raw_op_indexed_decorators(self)));
151
152 ops_offset
153 } else {
154 0
155 };
156
157 MastNodeInfo::new(mast_node, ops_offset)
158 })
159 .collect();
160
161 let basic_block_data = basic_block_data_builder.finalize();
162 basic_block_data.write_into(target);
163
164 for mast_node_info in mast_node_infos {
166 mast_node_info.write_into(target);
167 }
168
169 self.advice_map.write_into(target);
170 let error_codes: BTreeMap<u64, String> =
171 self.debug_info.error_codes().map(|(k, v)| (*k, v.to_string())).collect();
172 error_codes.write_into(target);
173
174 let mut decorator_data_builder = DecoratorDataBuilder::new();
177 for decorator in self.debug_info.decorators() {
178 decorator_data_builder.add_decorator(decorator)
179 }
180
181 let (decorator_data, decorator_infos, string_table) = decorator_data_builder.finalize();
182
183 decorator_data.write_into(target);
185 string_table.write_into(target);
186
187 for decorator_info in decorator_infos {
189 decorator_info.write_into(target);
190 }
191
192 basic_block_decorators.write_into(target);
193
194 before_enter_decorators.write_into(target);
196 after_exit_decorators.write_into(target);
197 }
198}
199
200impl Deserializable for MastForest {
201 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
202 read_and_validate_magic(source)?;
203 read_and_validate_version(source)?;
204
205 let node_count = source.read_usize()?;
207 let decorator_count = source.read_usize()?;
208
209 let roots: Vec<u32> = Deserializable::read_from(source)?;
211
212 let basic_block_data: Vec<u8> = Deserializable::read_from(source)?;
214 let mast_node_infos: Vec<MastNodeInfo> = node_infos_iter(source, node_count)
215 .collect::<Result<Vec<MastNodeInfo>, DeserializationError>>()?;
216
217 let advice_map = AdviceMap::read_from(source)?;
218
219 let error_codes: BTreeMap<u64, String> = Deserializable::read_from(source)?;
220 let error_codes: BTreeMap<u64, Arc<str>> =
221 error_codes.into_iter().map(|(k, v)| (k, Arc::from(v))).collect();
222
223 let decorator_data: Vec<u8> = Deserializable::read_from(source)?;
225 let string_table: StringTable = Deserializable::read_from(source)?;
226 let decorator_infos = decorator_infos_iter(source, decorator_count);
227
228 let mut mast_forest = {
230 let mut mast_forest = MastForest::new();
231
232 for decorator_info in decorator_infos {
233 let decorator_info = decorator_info?;
234 let decorator =
235 decorator_info.try_into_decorator(&string_table, &decorator_data)?;
236
237 mast_forest.add_decorator(decorator).map_err(|e| {
238 DeserializationError::InvalidValue(format!(
239 "failed to add decorator to MAST forest while deserializing: {e}",
240 ))
241 })?;
242 }
243
244 let basic_block_data_decoder = BasicBlockDataDecoder::new(&basic_block_data);
246 let mut mast_builders = mast_node_infos
247 .into_iter()
248 .map(|node_info| {
249 node_info.try_into_mast_node_builder(node_count, &basic_block_data_decoder)
250 })
251 .collect::<Result<Vec<_>, _>>()?;
252
253 let basic_block_decorators: Vec<(usize, DecoratorList)> =
254 read_block_decorators(source, mast_forest.debug_info.num_decorators())?;
255 for (node_id, decorator_list) in basic_block_decorators {
256 match &mut mast_builders[node_id] {
257 MastNodeBuilder::BasicBlock(basic_block) => {
258 basic_block.set_decorators(decorator_list);
259 },
260 other => {
261 return Err(DeserializationError::InvalidValue(format!(
262 "expected mast node with id {node_id} to be a basic block, found {other:?}"
263 )));
264 },
265 }
266 }
267
268 let before_enter_decorators: Vec<(usize, Vec<DecoratorId>)> =
270 read_before_after_decorators(source, mast_forest.debug_info.num_decorators())?;
271 for (node_id, decorator_ids) in before_enter_decorators {
272 mast_builders[node_id].append_before_enter(decorator_ids);
273 }
274
275 let after_exit_decorators: Vec<(usize, Vec<DecoratorId>)> =
276 read_before_after_decorators(source, mast_forest.debug_info.num_decorators())?;
277 for (node_id, decorator_ids) in after_exit_decorators {
278 mast_builders[node_id].append_after_exit(decorator_ids);
279 }
280
281 for mast_node_builder in mast_builders {
282 mast_node_builder.add_to_forest_relaxed(&mut mast_forest).map_err(|e| {
283 DeserializationError::InvalidValue(format!(
284 "failed to add node to MAST forest while deserializing: {e}",
285 ))
286 })?;
287 }
288
289 for root in roots {
291 let root = MastNodeId::from_u32_safe(root, &mast_forest)?;
293 mast_forest.make_root(root);
294 }
295
296 mast_forest.advice_map = advice_map;
297
298 mast_forest
299 };
300
301 mast_forest.debug_info.clear_error_codes();
302 mast_forest
303 .debug_info
304 .extend_error_codes(error_codes.iter().map(|(k, v)| (*k, v.clone())));
305
306 Ok(mast_forest)
307 }
308}
309
310fn read_and_validate_magic<R: ByteReader>(source: &mut R) -> Result<[u8; 5], DeserializationError> {
311 let magic: [u8; 5] = source.read_array()?;
312 if magic != *MAGIC {
313 return Err(DeserializationError::InvalidValue(format!(
314 "Invalid magic bytes. Expected '{:?}', got '{:?}'",
315 *MAGIC, magic
316 )));
317 }
318 Ok(magic)
319}
320
321fn read_and_validate_version<R: ByteReader>(
322 source: &mut R,
323) -> Result<[u8; 3], DeserializationError> {
324 let version: [u8; 3] = source.read_array()?;
325 if version != VERSION {
326 return Err(DeserializationError::InvalidValue(format!(
327 "Unsupported version. Got '{version:?}', but only '{VERSION:?}' is supported",
328 )));
329 }
330 Ok(version)
331}
332
333fn read_block_decorators<R: ByteReader>(
334 source: &mut R,
335 decorator_count: usize,
336) -> Result<Vec<(usize, DecoratorList)>, DeserializationError> {
337 let vec_len: usize = source.read()?;
338 let mut out_vec: Vec<_> = Vec::with_capacity(vec_len);
339
340 for _ in 0..vec_len {
341 let node_id: usize = source.read()?;
342
343 let decorator_vec_len: usize = source.read()?;
344 let mut inner_vec: Vec<DecoratedOpLink> = Vec::with_capacity(decorator_vec_len);
345 for _ in 0..decorator_vec_len {
346 let op_id: usize = source.read()?;
347 let decorator_id = DecoratorId::from_u32_bounded(source.read()?, decorator_count)?;
348 inner_vec.push((op_id, decorator_id));
349 }
350
351 out_vec.push((node_id, inner_vec));
352 }
353
354 Ok(out_vec)
355}
356
357fn decorator_infos_iter<'a, R>(
358 source: &'a mut R,
359 decorator_count: usize,
360) -> impl Iterator<Item = Result<DecoratorInfo, DeserializationError>> + 'a
361where
362 R: ByteReader + 'a,
363{
364 let mut remaining = decorator_count;
365 core::iter::from_fn(move || {
366 if remaining == 0 {
367 return None;
368 }
369 remaining -= 1;
370 Some(DecoratorInfo::read_from(source))
371 })
372}
373
374fn node_infos_iter<'a, R>(
375 source: &'a mut R,
376 node_count: usize,
377) -> impl Iterator<Item = Result<MastNodeInfo, DeserializationError>> + 'a
378where
379 R: ByteReader + 'a,
380{
381 let mut remaining = node_count;
382 core::iter::from_fn(move || {
383 if remaining == 0 {
384 return None;
385 }
386 remaining -= 1;
387 Some(MastNodeInfo::read_from(source))
388 })
389}
390
391fn read_before_after_decorators<R: ByteReader>(
397 source: &mut R,
398 decorator_count: usize,
399) -> Result<Vec<(usize, Vec<DecoratorId>)>, DeserializationError> {
400 let vec_len: usize = source.read()?;
401 let mut out_vec: Vec<_> = Vec::with_capacity(vec_len);
402
403 for _ in 0..vec_len {
404 let node_id: usize = source.read()?;
405
406 let inner_vec_len: usize = source.read()?;
407 let mut inner_vec: Vec<DecoratorId> = Vec::with_capacity(inner_vec_len);
408 for _ in 0..inner_vec_len {
409 let decorator_id = DecoratorId::from_u32_bounded(source.read()?, decorator_count)?;
410 inner_vec.push(decorator_id);
411 }
412
413 out_vec.push((node_id, inner_vec));
414 }
415
416 Ok(out_vec)
417}