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 ProgramCore<N> { 19 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> { 20 // Read the version. 21 let version = u8::read_le(&mut reader)?; 22 // Ensure the version is valid. 23 if version != 1 { 24 return Err(error("Invalid program version")); 25 } 26 27 // Read the program ID. 28 let id = ProgramID::read_le(&mut reader)?; 29 30 // Initialize the program. 31 let mut program = ProgramCore::new(id).map_err(error)?; 32 33 // Read the number of program imports. 34 let imports_len = u8::read_le(&mut reader)?; 35 // Read the program imports. 36 for _ in 0..imports_len { 37 program.add_import(Import::read_le(&mut reader)?).map_err(error)?; 38 } 39 40 // Read the number of components. 41 let components_len = u16::read_le(&mut reader)?; 42 for _ in 0..components_len { 43 // Read the variant. 44 let variant = u8::read_le(&mut reader)?; 45 // Match the variant. 46 match variant { 47 // Read the mapping. 48 0 => program.add_mapping(Mapping::read_le(&mut reader)?).map_err(error)?, 49 // Read the struct. 50 1 => program.add_struct(StructType::read_le(&mut reader)?).map_err(error)?, 51 // Read the record. 52 2 => program.add_record(RecordType::read_le(&mut reader)?).map_err(error)?, 53 // Read the closure. 54 3 => program.add_closure(ClosureCore::read_le(&mut reader)?).map_err(error)?, 55 // Read the function. 56 4 => program.add_function(FunctionCore::read_le(&mut reader)?).map_err(error)?, 57 // Read the constructor. 58 5 => program.add_constructor(ConstructorCore::read_le(&mut reader)?).map_err(error)?, 59 // Invalid variant. 60 _ => return Err(error(format!("Failed to parse program. Invalid component variant '{variant}'"))), 61 } 62 } 63 64 Ok(program) 65 } 66 } 67 68 impl<N: Network> ToBytes for ProgramCore<N> { 69 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> { 70 // Write the version. 71 1u8.write_le(&mut writer)?; 72 73 // Write the program ID. 74 self.id.write_le(&mut writer)?; 75 76 // Write the number of program imports. 77 u8::try_from(self.imports.len()).map_err(error)?.write_le(&mut writer)?; 78 // Write the program imports. 79 for import in self.imports.values() { 80 import.write_le(&mut writer)?; 81 } 82 83 // Write the number of components. 84 u16::try_from(self.components.len()).map_err(error)?.write_le(&mut writer)?; 85 86 // Write the components. 87 for (label, definition) in self.components.iter() { 88 match label { 89 ProgramLabel::Constructor => { 90 // Write the constructor, if it exists. 91 if let Some(constructor) = &self.constructor { 92 // Write the variant. 93 5u8.write_le(&mut writer)?; 94 // Write the constructor. 95 constructor.write_le(&mut writer)?; 96 } 97 } 98 ProgramLabel::Identifier(identifier) => { 99 match definition { 100 ProgramDefinition::Constructor => { 101 return Err(error("A program constructor cannot have a named label")); 102 } 103 ProgramDefinition::Mapping => match self.mappings.get(identifier) { 104 Some(mapping) => { 105 // Write the variant. 106 0u8.write_le(&mut writer)?; 107 // Write the mapping. 108 mapping.write_le(&mut writer)?; 109 } 110 None => return Err(error(format!("Mapping '{identifier}' is not defined"))), 111 }, 112 ProgramDefinition::Struct => match self.structs.get(identifier) { 113 Some(struct_) => { 114 // Write the variant. 115 1u8.write_le(&mut writer)?; 116 // Write the struct. 117 struct_.write_le(&mut writer)?; 118 } 119 None => return Err(error(format!("Struct '{identifier}' is not defined."))), 120 }, 121 ProgramDefinition::Record => match self.records.get(identifier) { 122 Some(record) => { 123 // Write the variant. 124 2u8.write_le(&mut writer)?; 125 // Write the record. 126 record.write_le(&mut writer)?; 127 } 128 None => return Err(error(format!("Record '{identifier}' is not defined."))), 129 }, 130 ProgramDefinition::Closure => match self.closures.get(identifier) { 131 Some(closure) => { 132 // Write the variant. 133 3u8.write_le(&mut writer)?; 134 // Write the closure. 135 closure.write_le(&mut writer)?; 136 } 137 None => return Err(error(format!("Closure '{identifier}' is not defined."))), 138 }, 139 ProgramDefinition::Function => match self.functions.get(identifier) { 140 Some(function) => { 141 // Write the variant. 142 4u8.write_le(&mut writer)?; 143 // Write the function. 144 function.write_le(&mut writer)?; 145 } 146 None => return Err(error(format!("Function '{identifier}' is not defined."))), 147 }, 148 } 149 } 150 } 151 } 152 Ok(()) 153 } 154 } 155 156 #[cfg(test)] 157 mod tests { 158 use super::*; 159 use crate::Program; 160 use console::network::MainnetV0; 161 162 type CurrentNetwork = MainnetV0; 163 164 #[test] 165 fn test_bytes() -> Result<()> { 166 let program = r" 167 program token.delta; 168 169 record token: 170 owner as address.private; 171 token_amount as u64.private; 172 173 function compute: 174 input r0 as token.record; 175 add r0.token_amount r0.token_amount into r1; 176 output r1 as u64.private;"; 177 178 // Initialize a new program. 179 let (string, expected) = Program::<CurrentNetwork>::parse(program).unwrap(); 180 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 181 182 let expected_bytes = expected.to_bytes_le()?; 183 184 let candidate = Program::<CurrentNetwork>::from_bytes_le(&expected_bytes)?; 185 assert_eq!(expected, candidate); 186 assert_eq!(expected_bytes, candidate.to_bytes_le()?); 187 188 Ok(()) 189 } 190 }