use super::*;
impl<N: Network> FromBytes for Request<N> {
fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
let version = u8::read_le(&mut reader)?;
if version != 1 && version != 2 {
return Err(error(format!("Invalid request version: {version}")));
}
let signer = FromBytes::read_le(&mut reader)?;
let network_id = FromBytes::read_le(&mut reader)?;
let program_id = FromBytes::read_le(&mut reader)?;
let function_name = FromBytes::read_le(&mut reader)?;
let inputs_len = u16::read_le(&mut reader)?;
if inputs_len as usize > N::MAX_INPUTS {
return Err(error(format!(
"Request (from 'read_le') has too many inputs ({inputs_len} > {})",
N::MAX_INPUTS
)));
}
let input_ids = (0..inputs_len).map(|_| FromBytes::read_le(&mut reader)).collect::<Result<Vec<_>, _>>()?;
let inputs = (0..inputs_len).map(|_| FromBytes::read_le(&mut reader)).collect::<Result<Vec<_>, _>>()?;
let signature = FromBytes::read_le(&mut reader)?;
let sk_tag = FromBytes::read_le(&mut reader)?;
let tvk = FromBytes::read_le(&mut reader)?;
let tcm = FromBytes::read_le(&mut reader)?;
let scm = FromBytes::read_le(&mut reader)?;
let is_dynamic = match version {
1 => false,
2 => bool::read_le(&mut reader)?,
_ => unreachable!(),
};
Ok(Self::from((
signer,
network_id,
program_id,
function_name,
input_ids,
inputs,
signature,
sk_tag,
tvk,
tcm,
scm,
is_dynamic,
)))
}
}
impl<N: Network> ToBytes for Request<N> {
fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
2u8.write_le(&mut writer)?;
self.signer.write_le(&mut writer)?;
self.network_id.write_le(&mut writer)?;
self.program_id.write_le(&mut writer)?;
self.function_name.write_le(&mut writer)?;
if self.input_ids.len() != self.inputs.len() {
return Err(error("Invalid request: mismatching number of input IDs and inputs"));
}
u16::try_from(self.input_ids.len())
.or_halt_with::<N>("Request inputs length exceeds u16")
.write_le(&mut writer)?;
for input_id in &self.input_ids {
input_id.write_le(&mut writer)?;
}
for input in &self.inputs {
input.write_le(&mut writer)?;
}
self.signature.write_le(&mut writer)?;
self.sk_tag.write_le(&mut writer)?;
self.tvk.write_le(&mut writer)?;
self.tcm.write_le(&mut writer)?;
self.scm.write_le(&mut writer)?;
self.is_dynamic.write_le(&mut writer)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bytes() {
let mut rng = TestRng::default();
for expected in test_helpers::sample_requests(&mut rng).into_iter() {
let expected_bytes = expected.to_bytes_le().unwrap();
assert_eq!(expected, Request::read_le(&expected_bytes[..]).unwrap());
}
}
}