bytes.rs
 1  // Copyright (c) 2025 ADnet Contributors
 2  // This file is part of the AlphaVM 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 ConstructorCore<N> {
19      /// Reads the constructor from a buffer.
20      #[inline]
21      fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
22          // Read the commands.
23          let num_commands = u16::read_le(&mut reader)?;
24          if num_commands.is_zero() {
25              return Err(error("Failed to deserialize constructor: needs at least one command"));
26          }
27          if num_commands > u16::try_from(N::MAX_COMMANDS).map_err(error)? {
28              return Err(error(format!("Failed to deserialize constructor: too many commands ({num_commands})")));
29          }
30          let mut commands = Vec::with_capacity(num_commands as usize);
31          for _ in 0..num_commands {
32              commands.push(Command::read_le(&mut reader)?);
33          }
34          // Initialize a new constructor.
35          let mut constructor = Self { commands: Default::default(), num_writes: 0, positions: Default::default() };
36          commands.into_iter().try_for_each(|command| constructor.add_command(command)).map_err(error)?;
37  
38          Ok(constructor)
39      }
40  }
41  
42  impl<N: Network> ToBytes for ConstructorCore<N> {
43      /// Writes the constructor to a buffer.
44      #[inline]
45      fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
46          // Write the number of commands for the constructor.
47          let num_commands = self.commands.len();
48          match 0 < num_commands && num_commands <= N::MAX_COMMANDS {
49              true => u16::try_from(num_commands).map_err(error)?.write_le(&mut writer)?,
50              false => return Err(error(format!("Failed to write {num_commands} commands as bytes"))),
51          }
52          // Write the commands.
53          for command in self.commands.iter() {
54              command.write_le(&mut writer)?;
55          }
56          Ok(())
57      }
58  }
59  
60  #[cfg(test)]
61  mod tests {
62      use super::*;
63      use crate::Constructor;
64      use console::network::MainnetV0;
65  
66      type CurrentNetwork = MainnetV0;
67  
68      #[test]
69      fn test_constructor_bytes() -> Result<()> {
70          let constructor_string = r"
71  constructor:
72      add r0 r1 into r2;
73      add r0 r1 into r3;
74      add r0 r1 into r4;
75      add r0 r1 into r5;
76      add r0 r1 into r6;
77      add r0 r1 into r7;
78      add r0 r1 into r8;
79      add r0 r1 into r9;
80      add r0 r1 into r10;
81      add r0 r1 into r11;
82      get accounts[r0] into r12;
83      get accounts[r1] into r13;";
84  
85          let expected = Constructor::<CurrentNetwork>::from_str(constructor_string)?;
86          let expected_bytes = expected.to_bytes_le()?;
87          println!("String size: {:?}, Bytecode size: {:?}", constructor_string.len(), expected_bytes.len());
88  
89          let candidate = Constructor::<CurrentNetwork>::from_bytes_le(&expected_bytes)?;
90          assert_eq!(expected.to_string(), candidate.to_string());
91          assert_eq!(expected_bytes, candidate.to_bytes_le()?);
92          Ok(())
93      }
94  }