diff --git a/assembly/src/ast/code_body.rs b/assembly/src/ast/code_body.rs index d6a82bc6fb..405da69007 100644 --- a/assembly/src/ast/code_body.rs +++ b/assembly/src/ast/code_body.rs @@ -26,8 +26,10 @@ impl CodeBody { where N: IntoIterator, { + let nodes: Vec<_> = nodes.into_iter().collect(); + assert!(nodes.len() <= u32::MAX.try_into().unwrap()); Self { - nodes: nodes.into_iter().collect(), + nodes, locations: Vec::new(), } } @@ -163,3 +165,35 @@ impl PartialEq for CodeBody { nodes && (locations || left_empty || right_empty) } } + +// SERIALIZATION +// ================================================================================================ + +impl Serializable for CodeBody { + fn write_into(&self, target: &mut W) { + assert!(self.nodes.len() <= u32::MAX.try_into().unwrap()); + target.write_u32(self.nodes.len() as u32); + self.nodes.write_into(target); + + target.write_u64(self.locations.len() as u64); + self.locations.write_into(target); + } +} + +impl Deserializable for CodeBody { + fn read_from(source: &mut R) -> Result { + let count = source + .read_u32()? + .try_into() + .map_err(|v| DeserializationError::InvalidValue(format!("can't fit {v} into usize")))?; + let nodes = Node::read_batch_from(source, count)?; + + let count = source + .read_u64()? + .try_into() + .map_err(|v| DeserializationError::InvalidValue(format!("can't fit {v} into usize")))?; + let locations = SourceLocation::read_batch_from(source, count)?; + + Ok(Self { nodes, locations }) + } +} diff --git a/assembly/src/ast/program.rs b/assembly/src/ast/program.rs index 12d3802b86..e166222b23 100644 --- a/assembly/src/ast/program.rs +++ b/assembly/src/ast/program.rs @@ -327,3 +327,37 @@ impl fmt::Display for ProgramAst { writeln!(f, "end") } } + +// SERIALIZATION +// ================================================================================================ + +impl Serializable for ProgramAst { + fn write_into(&self, target: &mut W) { + self.body.write_into(target); + + debug_assert!(self.local_procs.len() <= MAX_LOCAL_PROCS); + target.write_u16(self.local_procs.len() as u16); + + self.local_procs.write_into(target); + self.import_info.write_into(target); + self.start.write_into(target); + } +} + +impl Deserializable for ProgramAst { + fn read_from(source: &mut R) -> Result { + let body = CodeBody::read_from(source)?; + + let num_local_procs = source.read_u16()?.into(); + let local_procs = ProcedureAst::read_batch_from(source, num_local_procs)?; + let import_info = ModuleImports::read_from(source)?; + let start = SourceLocation::read_from(source)?; + + Ok(Self { + body, + local_procs, + import_info, + start, + }) + } +}