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 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 }