snarkvm_synthesizer_program/function/
bytes.rsuse super::*;
impl<N: Network, Instruction: InstructionTrait<N>, Command: CommandTrait<N>> FromBytes
for FunctionCore<N, Instruction, Command>
{
#[inline]
fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
let name = Identifier::<N>::read_le(&mut reader)?;
let num_inputs = u16::read_le(&mut reader)?;
if num_inputs > u16::try_from(N::MAX_INPUTS).map_err(error)? {
return Err(error(format!("Failed to deserialize a function: too many inputs ({num_inputs})")));
}
let mut inputs = Vec::with_capacity(num_inputs as usize);
for _ in 0..num_inputs {
inputs.push(Input::read_le(&mut reader)?);
}
let num_instructions = u32::read_le(&mut reader)?;
if num_instructions > u32::try_from(N::MAX_INSTRUCTIONS).map_err(error)? {
return Err(error(format!("Failed to deserialize a function: too many instructions ({num_instructions})")));
}
let mut instructions = Vec::with_capacity(num_instructions as usize);
for _ in 0..num_instructions {
instructions.push(Instruction::read_le(&mut reader)?);
}
let num_outputs = u16::read_le(&mut reader)?;
if num_outputs > u16::try_from(N::MAX_OUTPUTS).map_err(error)? {
return Err(error(format!("Failed to deserialize a function: too many outputs ({num_outputs})")));
}
let mut outputs = Vec::with_capacity(num_outputs as usize);
for _ in 0..num_outputs {
outputs.push(Output::read_le(&mut reader)?);
}
let variant = u8::read_le(&mut reader)?;
let finalize = match variant {
0 => None,
1 => Some(FinalizeCore::read_le(&mut reader)?),
_ => return Err(error(format!("Failed to deserialize a function: invalid finalize variant ({variant})"))),
};
let mut function = Self::new(name);
inputs.into_iter().try_for_each(|input| function.add_input(input)).map_err(error)?;
instructions.into_iter().try_for_each(|instruction| function.add_instruction(instruction)).map_err(error)?;
outputs.into_iter().try_for_each(|output| function.add_output(output)).map_err(error)?;
finalize.map(|finalize| function.add_finalize(finalize));
Ok(function)
}
}
impl<N: Network, Instruction: InstructionTrait<N>, Command: CommandTrait<N>> ToBytes
for FunctionCore<N, Instruction, Command>
{
#[inline]
fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
self.name.write_le(&mut writer)?;
let num_inputs = self.inputs.len();
match num_inputs <= N::MAX_INPUTS {
true => u16::try_from(num_inputs).map_err(error)?.write_le(&mut writer)?,
false => return Err(error(format!("Failed to write {num_inputs} inputs as bytes"))),
}
for input in self.inputs.iter() {
input.write_le(&mut writer)?;
}
let num_instructions = self.instructions.len();
match num_instructions <= N::MAX_INSTRUCTIONS {
true => u32::try_from(num_instructions).map_err(error)?.write_le(&mut writer)?,
false => return Err(error(format!("Failed to write {num_instructions} instructions as bytes"))),
}
for instruction in self.instructions.iter() {
instruction.write_le(&mut writer)?;
}
let num_outputs = self.outputs.len();
match num_outputs <= N::MAX_OUTPUTS {
true => u16::try_from(num_outputs).map_err(error)?.write_le(&mut writer)?,
false => return Err(error(format!("Failed to write {num_outputs} outputs as bytes"))),
}
for output in self.outputs.iter() {
output.write_le(&mut writer)?;
}
match &self.finalize_logic {
None => 0u8.write_le(&mut writer)?,
Some(logic) => {
1u8.write_le(&mut writer)?;
logic.write_le(&mut writer)?;
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Function;
use console::network::MainnetV0;
type CurrentNetwork = MainnetV0;
#[test]
fn test_function_bytes() -> Result<()> {
let function_string = r"
function main:
input r0 as field.public;
input r1 as field.private;
add r0 r1 into r2;
add r0 r1 into r3;
add r0 r1 into r4;
add r0 r1 into r5;
add r0 r1 into r6;
add r0 r1 into r7;
add r0 r1 into r8;
add r0 r1 into r9;
add r0 r1 into r10;
add r0 r1 into r11;
output r11 as field.private;";
let expected = Function::<CurrentNetwork>::from_str(function_string)?;
let expected_bytes = expected.to_bytes_le()?;
println!("String size: {:?}, Bytecode size: {:?}", function_string.as_bytes().len(), expected_bytes.len());
let candidate = Function::<CurrentNetwork>::from_bytes_le(&expected_bytes)?;
assert_eq!(expected.to_string(), candidate.to_string());
assert_eq!(expected_bytes, candidate.to_bytes_le()?);
Ok(())
}
}