snarkvm_synthesizer_program/
bytes.rsuse super::*;
impl<N: Network, Instruction: InstructionTrait<N>, Command: CommandTrait<N>> FromBytes
for ProgramCore<N, Instruction, Command>
{
fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
let version = u8::read_le(&mut reader)?;
if version != 1 {
return Err(error("Invalid program version"));
}
let id = ProgramID::read_le(&mut reader)?;
let mut program = ProgramCore::new(id).map_err(|e| error(e.to_string()))?;
let imports_len = u8::read_le(&mut reader)?;
for _ in 0..imports_len {
program.add_import(Import::read_le(&mut reader)?).map_err(|e| error(e.to_string()))?;
}
let components_len = u16::read_le(&mut reader)?;
for _ in 0..components_len {
let variant = u8::read_le(&mut reader)?;
match variant {
0 => program.add_mapping(Mapping::read_le(&mut reader)?).map_err(|e| error(e.to_string()))?,
1 => program.add_struct(StructType::read_le(&mut reader)?).map_err(|e| error(e.to_string()))?,
2 => program.add_record(RecordType::read_le(&mut reader)?).map_err(|e| error(e.to_string()))?,
3 => program.add_closure(ClosureCore::read_le(&mut reader)?).map_err(|e| error(e.to_string()))?,
4 => program.add_function(FunctionCore::read_le(&mut reader)?).map_err(|e| error(e.to_string()))?,
_ => return Err(error(format!("Failed to parse program. Invalid component variant '{variant}'"))),
}
}
Ok(program)
}
}
impl<N: Network, Instruction: InstructionTrait<N>, Command: CommandTrait<N>> ToBytes
for ProgramCore<N, Instruction, Command>
{
fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
1u8.write_le(&mut writer)?;
self.id.write_le(&mut writer)?;
u8::try_from(self.imports.len()).map_err(|e| error(e.to_string()))?.write_le(&mut writer)?;
for import in self.imports.values() {
import.write_le(&mut writer)?;
}
u16::try_from(self.identifiers.len()).map_err(|e| error(e.to_string()))?.write_le(&mut writer)?;
for (identifier, definition) in self.identifiers.iter() {
match definition {
ProgramDefinition::Mapping => match self.mappings.get(identifier) {
Some(mapping) => {
0u8.write_le(&mut writer)?;
mapping.write_le(&mut writer)?;
}
None => return Err(error(format!("Mapping '{identifier}' is not defined"))),
},
ProgramDefinition::Struct => match self.structs.get(identifier) {
Some(struct_) => {
1u8.write_le(&mut writer)?;
struct_.write_le(&mut writer)?;
}
None => return Err(error(format!("Struct '{identifier}' is not defined."))),
},
ProgramDefinition::Record => match self.records.get(identifier) {
Some(record) => {
2u8.write_le(&mut writer)?;
record.write_le(&mut writer)?;
}
None => return Err(error(format!("Record '{identifier}' is not defined."))),
},
ProgramDefinition::Closure => match self.closures.get(identifier) {
Some(closure) => {
3u8.write_le(&mut writer)?;
closure.write_le(&mut writer)?;
}
None => return Err(error(format!("Closure '{identifier}' is not defined."))),
},
ProgramDefinition::Function => match self.functions.get(identifier) {
Some(function) => {
4u8.write_le(&mut writer)?;
function.write_le(&mut writer)?;
}
None => return Err(error(format!("Function '{identifier}' is not defined."))),
},
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Program;
use console::network::MainnetV0;
type CurrentNetwork = MainnetV0;
#[test]
fn test_bytes() -> Result<()> {
let program = r"
program token.aleo;
record token:
owner as address.private;
token_amount as u64.private;
function compute:
input r0 as token.record;
add r0.token_amount r0.token_amount into r1;
output r1 as u64.private;";
let (string, expected) = Program::<CurrentNetwork>::parse(program).unwrap();
assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
let expected_bytes = expected.to_bytes_le()?;
let candidate = Program::<CurrentNetwork>::from_bytes_le(&expected_bytes)?;
assert_eq!(expected, candidate);
assert_eq!(expected_bytes, candidate.to_bytes_le()?);
Ok(())
}
}