snarkvm_synthesizer_program/
bytes.rs1use super::*;
17
18impl<N: Network> FromBytes for ProgramCore<N> {
19 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
20 let version = u8::read_le(&mut reader)?;
22 if version != 1 {
24 return Err(error("Invalid program version"));
25 }
26
27 let id = ProgramID::read_le(&mut reader)?;
29
30 let mut program = ProgramCore::new(id).map_err(error)?;
32
33 let imports_len = u8::read_le(&mut reader)?;
35 for _ in 0..imports_len {
37 program.add_import(Import::read_le(&mut reader)?).map_err(error)?;
38 }
39
40 let components_len = u16::read_le(&mut reader)?;
42 for _ in 0..components_len {
43 let variant = u8::read_le(&mut reader)?;
45 match variant {
47 0 => program.add_mapping(Mapping::read_le(&mut reader)?).map_err(error)?,
49 1 => program.add_struct(StructType::read_le(&mut reader)?).map_err(error)?,
51 2 => program.add_record(RecordType::read_le(&mut reader)?).map_err(error)?,
53 3 => program.add_closure(ClosureCore::read_le(&mut reader)?).map_err(error)?,
55 4 => program.add_function(FunctionCore::read_le(&mut reader)?).map_err(error)?,
57 5 => program.add_constructor(ConstructorCore::read_le(&mut reader)?).map_err(error)?,
59 _ => return Err(error(format!("Failed to parse program. Invalid component variant '{variant}'"))),
61 }
62 }
63
64 Ok(program)
65 }
66}
67
68impl<N: Network> ToBytes for ProgramCore<N> {
69 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
70 1u8.write_le(&mut writer)?;
72
73 self.id.write_le(&mut writer)?;
75
76 u8::try_from(self.imports.len()).map_err(error)?.write_le(&mut writer)?;
78 for import in self.imports.values() {
80 import.write_le(&mut writer)?;
81 }
82
83 u16::try_from(self.components.len()).map_err(error)?.write_le(&mut writer)?;
85
86 for (label, definition) in self.components.iter() {
88 match label {
89 ProgramLabel::Constructor => {
90 if let Some(constructor) = &self.constructor {
92 5u8.write_le(&mut writer)?;
94 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 0u8.write_le(&mut writer)?;
107 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 1u8.write_le(&mut writer)?;
116 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 2u8.write_le(&mut writer)?;
125 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 3u8.write_le(&mut writer)?;
134 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 4u8.write_le(&mut writer)?;
143 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)]
157mod 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"
167program token.aleo;
168
169record token:
170 owner as address.private;
171 token_amount as u64.private;
172
173function 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 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}