/ synthesizer / program / src / closure / bytes.rs
bytes.rs
  1  // Copyright (c) 2019-2025 Alpha-Delta Network Inc.
  2  // This file is part of the deltavm library.
  3  
  4  // Licensed under the Apache License, Version 2.0 (the "License");
  5  // you may not use this file except in compliance with the License.
  6  // You may obtain a copy of the License at:
  7  
  8  // http://www.apache.org/licenses/LICENSE-2.0
  9  
 10  // Unless required by applicable law or agreed to in writing, software
 11  // distributed under the License is distributed on an "AS IS" BASIS,
 12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  // See the License for the specific language governing permissions and
 14  // limitations under the License.
 15  
 16  use super::*;
 17  
 18  impl<N: Network> FromBytes for ClosureCore<N> {
 19      /// Reads the closure from a buffer.
 20      #[inline]
 21      fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
 22          // Read the closure name.
 23          let name = Identifier::<N>::read_le(&mut reader)?;
 24  
 25          // Read the inputs.
 26          let num_inputs = u16::read_le(&mut reader)?;
 27          if num_inputs.is_zero() {
 28              return Err(error("Failed to deserialize a closure: needs at least one input".to_string()));
 29          }
 30          if num_inputs > u16::try_from(N::MAX_INPUTS).map_err(error)? {
 31              return Err(error(format!("Failed to deserialize a closure: too many inputs ({num_inputs})")));
 32          }
 33          let mut inputs = Vec::with_capacity(num_inputs as usize);
 34          for _ in 0..num_inputs {
 35              inputs.push(Input::read_le(&mut reader)?);
 36          }
 37  
 38          // Read the instructions.
 39          let num_instructions = u32::read_le(&mut reader)?;
 40          if num_instructions.is_zero() {
 41              return Err(error("Failed to deserialize a closure: needs at least one instruction".to_string()));
 42          }
 43          if num_instructions > u32::try_from(N::MAX_INSTRUCTIONS).map_err(error)? {
 44              return Err(error(format!("Failed to deserialize a closure: too many instructions ({num_instructions})")));
 45          }
 46          let mut instructions = Vec::with_capacity(num_instructions as usize);
 47          for _ in 0..num_instructions {
 48              instructions.push(Instruction::read_le(&mut reader)?);
 49          }
 50  
 51          // Read the outputs.
 52          let num_outputs = u16::read_le(&mut reader)?;
 53          if num_outputs > u16::try_from(N::MAX_OUTPUTS).map_err(error)? {
 54              return Err(error(format!("Failed to deserialize a closure: too many outputs ({num_outputs})")));
 55          }
 56          let mut outputs = Vec::with_capacity(num_outputs as usize);
 57          for _ in 0..num_outputs {
 58              outputs.push(Output::read_le(&mut reader)?);
 59          }
 60  
 61          // Initialize a new closure.
 62          let mut closure = Self::new(name);
 63          inputs.into_iter().try_for_each(|input| closure.add_input(input)).map_err(error)?;
 64          instructions.into_iter().try_for_each(|instruction| closure.add_instruction(instruction)).map_err(error)?;
 65          outputs.into_iter().try_for_each(|output| closure.add_output(output)).map_err(error)?;
 66  
 67          Ok(closure)
 68      }
 69  }
 70  
 71  impl<N: Network> ToBytes for ClosureCore<N> {
 72      /// Writes the closure to a buffer.
 73      #[inline]
 74      fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
 75          // Write the closure name.
 76          self.name.write_le(&mut writer)?;
 77  
 78          // Write the number of inputs for the closure.
 79          let num_inputs = self.inputs.len();
 80          match 0 < num_inputs && num_inputs <= N::MAX_INPUTS {
 81              true => u16::try_from(num_inputs).map_err(error)?.write_le(&mut writer)?,
 82              false => return Err(error(format!("Failed to write {num_inputs} inputs as bytes"))),
 83          }
 84  
 85          // Write the inputs.
 86          for input in self.inputs.iter() {
 87              input.write_le(&mut writer)?;
 88          }
 89  
 90          // Write the number of instructions for the closure.
 91          let num_instructions = self.instructions.len();
 92          match 0 < num_instructions && num_instructions <= N::MAX_INSTRUCTIONS {
 93              true => u32::try_from(num_instructions).map_err(error)?.write_le(&mut writer)?,
 94              false => return Err(error(format!("Failed to write {num_instructions} instructions as bytes"))),
 95          }
 96  
 97          // Write the instructions.
 98          for instruction in self.instructions.iter() {
 99              instruction.write_le(&mut writer)?;
100          }
101  
102          // Write the number of outputs for the closure.
103          let num_outputs = self.outputs.len();
104          match num_outputs <= N::MAX_OUTPUTS {
105              true => u16::try_from(num_outputs).map_err(error)?.write_le(&mut writer)?,
106              false => return Err(error(format!("Failed to write {num_outputs} outputs as bytes"))),
107          }
108  
109          // Write the outputs.
110          for output in self.outputs.iter() {
111              output.write_le(&mut writer)?;
112          }
113  
114          Ok(())
115      }
116  }
117  
118  #[cfg(test)]
119  mod tests {
120      use super::*;
121      use crate::Closure;
122      use console::network::MainnetV0;
123  
124      type CurrentNetwork = MainnetV0;
125  
126      #[test]
127      fn test_closure_bytes() -> Result<()> {
128          let closure_string = r"
129  closure main:
130      input r0 as field;
131      input r1 as field;
132      add r0 r1 into r2;
133      add r0 r1 into r3;
134      add r0 r1 into r4;
135      add r0 r1 into r5;
136      add r0 r1 into r6;
137      add r0 r1 into r7;
138      add r0 r1 into r8;
139      add r0 r1 into r9;
140      add r0 r1 into r10;
141      add r0 r1 into r11;
142      output r11 as field;";
143  
144          let expected = Closure::<CurrentNetwork>::from_str(closure_string)?;
145          let expected_bytes = expected.to_bytes_le()?;
146          println!("String size: {:?}, Bytecode size: {:?}", closure_string.len(), expected_bytes.len());
147  
148          let candidate = Closure::<CurrentNetwork>::from_bytes_le(&expected_bytes)?;
149          assert_eq!(expected.to_string(), candidate.to_string());
150          assert_eq!(expected_bytes, candidate.to_bytes_le()?);
151          Ok(())
152      }
153  }