1use crate::{Opcode, Operand, RegistersCircuit, RegistersTrait, StackTrait};
17use console::{
18 network::prelude::*,
19 program::{
20 ArrayType,
21 Identifier,
22 Literal,
23 LiteralType,
24 Locator,
25 Plaintext,
26 PlaintextType,
27 Register,
28 RegisterType,
29 StructType,
30 U8,
31 U16,
32 U32,
33 Value,
34 },
35};
36
37use indexmap::IndexMap;
38
39pub type DeserializeBits<N> = DeserializeInstruction<N, { DeserializeVariant::FromBits as u8 }>;
41pub type DeserializeBitsRaw<N> = DeserializeInstruction<N, { DeserializeVariant::FromBitsRaw as u8 }>;
43
44#[derive(Debug, Clone, Eq, PartialEq)]
46pub enum DeserializeVariant {
47 FromBits,
48 FromBitsRaw,
49}
50
51impl DeserializeVariant {
52 pub const fn opcode(variant: u8) -> &'static str {
54 match variant {
55 0 => "deserialize.bits",
56 1 => "deserialize.bits.raw",
57 _ => panic!("Invalid 'deserialize' instruction opcode"),
58 }
59 }
60
61 pub const fn from_u8(variant: u8) -> Self {
63 match variant {
64 0 => Self::FromBits,
65 1 => Self::FromBitsRaw,
66 _ => panic!("Invalid 'deserialize' instruction variant"),
67 }
68 }
69}
70
71fn check_number_of_operands(variant: u8, num_operands: usize) -> Result<()> {
73 if num_operands != 1 {
74 bail!("Instruction '{}' expects 1 operand, found {num_operands} operands", DeserializeVariant::opcode(variant))
75 }
76 Ok(())
77}
78
79fn check_operand_type_is_valid(variant: u8, array_type: &ArrayType<impl Network>) -> Result<()> {
81 match variant {
82 0 | 1 if array_type.is_bit_array() => Ok(()),
83 _ => {
84 bail!("Instruction '{}' cannot output type '{array_type}'", DeserializeVariant::opcode(variant))
85 }
86 }
87}
88
89fn check_destination_type_is_valid(variant: u8, destination_type: &PlaintextType<impl Network>) -> Result<()> {
91 fn check_literal_type(literal_type: &LiteralType) -> Result<()> {
93 match literal_type {
94 LiteralType::Address
95 | LiteralType::Boolean
96 | LiteralType::Field
97 | LiteralType::Group
98 | LiteralType::I8
99 | LiteralType::I16
100 | LiteralType::I32
101 | LiteralType::I64
102 | LiteralType::I128
103 | LiteralType::U8
104 | LiteralType::U16
105 | LiteralType::U32
106 | LiteralType::U64
107 | LiteralType::U128
108 | LiteralType::Scalar => Ok(()),
109 _ => bail!("Invalid literal type '{literal_type}' for 'deserialize' instruction"),
110 }
111 }
112
113 match destination_type {
114 PlaintextType::Literal(literal_type) => check_literal_type(literal_type),
115 PlaintextType::Array(array_type) => match array_type.base_element_type() {
116 PlaintextType::Literal(literal_type) => check_literal_type(literal_type),
117 _ => bail!("Invalid element type '{array_type}' for 'deserialize' instruction"),
118 },
119 _ => bail!(
120 "Instruction '{}' cannot take type '{destination_type}' as input",
121 DeserializeVariant::opcode(variant)
122 ),
123 }
124}
125
126#[derive(Clone, PartialEq, Eq, Hash)]
128pub struct DeserializeInstruction<N: Network, const VARIANT: u8> {
129 operands: Vec<Operand<N>>,
131 operand_type: ArrayType<N>,
133 destination: Register<N>,
135 destination_type: PlaintextType<N>,
137}
138
139impl<N: Network, const VARIANT: u8> DeserializeInstruction<N, VARIANT> {
140 pub fn new(
142 operands: Vec<Operand<N>>,
143 operand_type: ArrayType<N>,
144 destination: Register<N>,
145 destination_type: PlaintextType<N>,
146 ) -> Result<Self> {
147 check_number_of_operands(VARIANT, operands.len())?;
149 check_operand_type_is_valid(VARIANT, &operand_type)?;
151 check_destination_type_is_valid(VARIANT, &destination_type)?;
153 Ok(Self { operands, operand_type, destination, destination_type })
155 }
156
157 pub const fn opcode() -> Opcode {
159 Opcode::Deserialize(DeserializeVariant::opcode(VARIANT))
160 }
161
162 pub fn operands(&self) -> &[Operand<N>] {
164 if cfg!(debug_assertions) {
166 check_number_of_operands(VARIANT, self.operands.len()).unwrap();
167 check_operand_type_is_valid(VARIANT, &self.operand_type).unwrap();
168 check_destination_type_is_valid(VARIANT, &self.destination_type).unwrap();
169 }
170 &self.operands
172 }
173
174 pub const fn operand_type(&self) -> &ArrayType<N> {
176 &self.operand_type
177 }
178
179 #[inline]
181 pub fn destinations(&self) -> Vec<Register<N>> {
182 vec![self.destination.clone()]
183 }
184
185 #[inline]
187 pub const fn destination_type(&self) -> &PlaintextType<N> {
188 &self.destination_type
189 }
190
191 #[inline]
193 pub fn contains_external_struct(&self) -> bool {
194 self.destination_type.contains_external_struct()
195 }
196}
197
198pub fn evaluate_deserialize<N: Network, F0, F1>(
203 variant: DeserializeVariant,
204 bits: &[bool],
205 destination_type: &PlaintextType<N>,
206 get_struct: &F0,
207 get_external_struct: &F1,
208) -> Result<Plaintext<N>>
209where
210 F0: Fn(&Identifier<N>) -> Result<StructType<N>>,
211 F1: Fn(&Locator<N>) -> Result<StructType<N>>,
212{
213 evaluate_deserialize_internal(variant as u8, bits, destination_type, get_struct, get_external_struct, 0)
214}
215
216fn evaluate_deserialize_internal<N: Network, F0, F1>(
217 variant: u8,
218 bits: &[bool],
219 destination_type: &PlaintextType<N>,
220 get_struct: &F0,
221 get_external_struct: &F1,
222 depth: usize,
223) -> Result<Plaintext<N>>
224where
225 F0: Fn(&Identifier<N>) -> Result<StructType<N>>,
226 F1: Fn(&Locator<N>) -> Result<StructType<N>>,
227{
228 if depth > N::MAX_DATA_DEPTH {
230 bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH)
231 }
232
233 let get_size_in_bits = |plaintext_type: &PlaintextType<N>| -> Result<usize> {
235 match DeserializeVariant::from_u8(variant) {
236 DeserializeVariant::FromBits => plaintext_type.size_in_bits(get_struct, &get_external_struct),
237 DeserializeVariant::FromBitsRaw => plaintext_type.size_in_bits_raw(get_struct, &get_external_struct),
238 }
239 };
240
241 let size_in_bits = get_size_in_bits(destination_type)?;
243
244 let bits = bits.to_vec();
246 ensure!(
247 bits.len() == size_in_bits,
248 "The number of bits of the operand '{}' does not match the destination '{size_in_bits}'",
249 bits.len()
250 );
251
252 let mut index = 0;
254
255 let mut next_bits = |n: usize| -> Result<&[bool]> {
257 let subslice = bits.get(index..index + n);
259 if let Some(next_bits) = subslice {
261 index += n;
263 Ok(next_bits)
265 } else {
266 bail!("Insufficient bits");
267 }
268 };
269
270 let mut deserialize_struct = |struct_: &StructType<N>| -> Result<Plaintext<N>> {
272 if variant == (DeserializeVariant::FromBits as u8) {
274 let plaintext_variant = next_bits(2)?;
275 let plaintext_variant = [plaintext_variant[0], plaintext_variant[1]];
276 ensure!(
277 plaintext_variant == PlaintextType::<N>::STRUCT_PREFIX_BITS,
278 "Invalid plaintext variant for struct type"
279 );
280
281 let num_members = u8::from_bits_le(next_bits(8)?)?;
282 ensure!(struct_.members().len() == num_members as usize, "Struct exceeds maximum of entries.");
283 }
284
285 let mut members = IndexMap::with_capacity(struct_.members().len());
287
288 for (member_identifier, member_type) in struct_.members().iter() {
289 let expected_member_size = get_size_in_bits(member_type)?;
290
291 if variant == (DeserializeVariant::FromBits as u8) {
292 let identifier_size = u8::from_bits_le(next_bits(8)?)?;
293 ensure!(
294 member_identifier.size_in_bits() == identifier_size,
295 "Mismatched identifier size. Expected '{}', found '{}'",
296 member_identifier.size_in_bits(),
297 identifier_size
298 );
299
300 let identifier_bits = next_bits(identifier_size as usize)?;
301 let identifier = Identifier::<N>::from_bits_le(identifier_bits)?;
302 ensure!(
303 *member_identifier == identifier,
304 "Mismatched identifier. Expected '{member_identifier}', found '{identifier}'",
305 );
306
307 let member_size = u16::from_bits_le(next_bits(16)?)?;
308 ensure!(
309 member_size as usize == expected_member_size,
310 "Mismatched member size. Expected '{expected_member_size}', found '{member_size}'",
311 );
312 }
313
314 let value = evaluate_deserialize_internal(
315 variant,
316 next_bits(expected_member_size)?,
317 member_type,
318 get_struct,
319 get_external_struct,
320 depth + 1,
321 )?;
322
323 if members.insert(*member_identifier, value).is_some() {
324 bail!("Duplicate identifier in struct.");
325 }
326 }
327
328 Ok(Plaintext::Struct(members, Default::default()))
329 };
330
331 match destination_type {
332 PlaintextType::Literal(literal_type) => {
333 let expected_size = literal_type.size_in_bits::<N>();
335
336 if variant == (DeserializeVariant::FromBits as u8) {
338 let plaintext_variant = next_bits(2)?;
339 let plaintext_variant = [plaintext_variant[0], plaintext_variant[1]];
340 ensure!(
341 plaintext_variant == PlaintextType::<N>::LITERAL_PREFIX_BITS,
342 "Invalid plaintext variant for literal type '{literal_type}'"
343 );
344
345 let literal_variant = u8::from_bits_le(next_bits(8)?)?;
346 ensure!(
347 literal_variant == literal_type.type_id(),
348 "Mismatched literal type. Expected '{literal_type}', found '{literal_variant}'"
349 );
350
351 let literal_size = u16::from_bits_le(next_bits(16)?)?;
352 ensure!(
353 literal_size == expected_size,
354 "Mismatched literal size. Expected '{expected_size}', found '{literal_size}'",
355 );
356 };
357 let literal = Literal::from_bits_le(literal_type.type_id(), next_bits(expected_size as usize)?)?;
359 Ok(Plaintext::Literal(literal, Default::default()))
360 }
361 PlaintextType::Struct(identifier) => {
362 let struct_ = get_struct(identifier)?;
364 deserialize_struct(&struct_)
365 }
366 PlaintextType::ExternalStruct(locator) => {
367 let struct_ = get_external_struct(locator)?;
369 deserialize_struct(&struct_)
370 }
371 PlaintextType::Array(array_type) => {
372 if variant == (DeserializeVariant::FromBits as u8) {
374 let plaintext_variant = next_bits(2)?;
375 let plaintext_variant = [plaintext_variant[0], plaintext_variant[1]];
376 ensure!(
377 plaintext_variant == PlaintextType::<N>::ARRAY_PREFIX_BITS,
378 "Invalid plaintext variant for array type"
379 );
380
381 let num_elements = u32::from_bits_le(next_bits(32)?)?;
382 ensure!(
383 **array_type.length() == num_elements,
384 "Mismatched array length. Expected '{}', found '{}'",
385 **array_type.length(),
386 num_elements
387 );
388 }
389
390 let expected_element_type = array_type.next_element_type();
391 let expected_element_size = get_size_in_bits(expected_element_type)?;
392
393 let mut elements = Vec::with_capacity(**array_type.length() as usize);
394
395 for _ in 0..**array_type.length() {
396 if variant == (DeserializeVariant::FromBits as u8) {
397 let element_size = u16::from_bits_le(next_bits(16)?)?;
398 ensure!(
399 element_size as usize == expected_element_size,
400 "Mismatched element size. Expected '{expected_element_size}', found '{element_size}'",
401 );
402 }
403 let element = evaluate_deserialize_internal(
404 variant,
405 next_bits(expected_element_size)?,
406 expected_element_type,
407 get_struct,
408 get_external_struct,
409 depth + 1,
410 )?;
411 elements.push(element);
412 }
413
414 Ok(Plaintext::Array(elements, Default::default()))
416 }
417 }
418}
419
420fn execute_deserialize_internal<A: circuit::Aleo<Network = N>, N: Network, F0, F1>(
421 variant: u8,
422 bits: &[circuit::Boolean<A>],
423 destination_type: &PlaintextType<N>,
424 get_struct: &F0,
425 get_external_struct: &F1,
426 depth: usize,
427) -> Result<circuit::Plaintext<A>>
428where
429 F0: Fn(&Identifier<N>) -> Result<StructType<N>>,
430 F1: Fn(&Locator<N>) -> Result<StructType<N>>,
431{
432 use snarkvm_circuit::{Inject, traits::FromBits};
433
434 if depth > A::Network::MAX_DATA_DEPTH {
436 bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH)
437 }
438
439 let get_size_in_bits = |plaintext_type: &PlaintextType<N>| -> Result<usize> {
441 match DeserializeVariant::from_u8(variant) {
442 DeserializeVariant::FromBits => plaintext_type.size_in_bits(get_struct, get_external_struct),
443 DeserializeVariant::FromBitsRaw => plaintext_type.size_in_bits_raw(get_struct, get_external_struct),
444 }
445 };
446
447 let size_in_bits = get_size_in_bits(destination_type)?;
449
450 let bits = bits.to_vec();
452 ensure!(
453 bits.len() == size_in_bits,
454 "The number of bits of the operand '{}' does not match the destination '{size_in_bits}'",
455 bits.len()
456 );
457
458 let mut index = 0;
460
461 let mut next_bits = |n: usize| -> Result<&[circuit::Boolean<A>]> {
463 let subslice = bits.get(index..index + n);
465 if let Some(next_bits) = subslice {
467 index += n;
469 Ok(next_bits)
471 } else {
472 bail!("Insufficient bits");
473 }
474 };
475
476 let mut deserialize_struct = |struct_: &StructType<N>| -> Result<circuit::Plaintext<A>> {
478 let expected_num_members =
480 u8::try_from(struct_.members().len()).map_err(|_| anyhow!("Struct exceeds maximum of entries."))?;
481
482 if variant == (DeserializeVariant::FromBits as u8) {
484 let plaintext_variant = next_bits(2)?;
485 let expected_bits = PlaintextType::<A::Network>::STRUCT_PREFIX_BITS.map(circuit::Boolean::<A>::constant);
486 A::assert_eq(&expected_bits[0], &plaintext_variant[0]);
487 A::assert_eq(&expected_bits[1], &plaintext_variant[1]);
488
489 let num_members = circuit::U8::<A>::from_bits_le(next_bits(8)?);
490 A::assert_eq(num_members, circuit::U8::<A>::constant(U8::new(expected_num_members)));
491 }
492
493 let mut members = IndexMap::with_capacity(struct_.members().len());
495
496 for (member_identifier, member_type) in struct_.members().iter() {
497 let expected_member_size = u16::try_from(get_size_in_bits(member_type)?)
499 .map_err(|_| anyhow!("Member size exceeds maximum of 65535 bits."))?;
500
501 if variant == (DeserializeVariant::FromBits as u8) {
503 let expected_identifier_size = member_identifier.size_in_bits();
504 let identifier_size = circuit::U8::<A>::from_bits_le(next_bits(8)?);
505 A::assert_eq(&identifier_size, circuit::U8::<A>::constant(U8::new(expected_identifier_size)));
506
507 let identifier_bits = next_bits(expected_identifier_size as usize)?;
508 let identifier = circuit::Identifier::<A>::from_bits_le(identifier_bits);
509 A::assert_eq(circuit::Identifier::<A>::constant(*member_identifier), &identifier);
510
511 let member_size = circuit::U16::<A>::from_bits_le(next_bits(16)?);
512 A::assert_eq(&member_size, circuit::U16::<A>::constant(U16::new(expected_member_size)));
513 }
514
515 let value = execute_deserialize_internal(
516 variant,
517 next_bits(expected_member_size as usize)?,
518 member_type,
519 get_struct,
520 get_external_struct,
521 depth + 1,
522 )?;
523
524 if members.insert(circuit::Identifier::constant(*member_identifier), value).is_some() {
525 bail!("Duplicate identifier in struct.");
526 }
527 }
528
529 Ok(circuit::Plaintext::Struct(members, Default::default()))
531 };
532
533 match destination_type {
534 PlaintextType::Literal(literal_type) => {
535 let expected_size = literal_type.size_in_bits::<A::Network>();
537
538 if variant == (DeserializeVariant::FromBits as u8) {
540 let plaintext_variant = next_bits(2)?;
541 let expected_bits =
542 PlaintextType::<A::Network>::LITERAL_PREFIX_BITS.map(circuit::Boolean::<A>::constant);
543 A::assert_eq(&expected_bits[0], &plaintext_variant[0]);
544 A::assert_eq(&expected_bits[1], &plaintext_variant[1]);
545
546 let literal_variant = circuit::U8::<A>::from_bits_le(next_bits(8)?);
547 A::assert_eq(&literal_variant, circuit::U8::<A>::constant(U8::new(literal_type.type_id())));
548
549 let literal_size = circuit::U16::<A>::from_bits_le(next_bits(16)?);
550 A::assert_eq(&literal_size, circuit::U16::<A>::constant(U16::new(expected_size)));
551 };
552 let literal = circuit::Literal::<A>::from_bits_le(
554 &circuit::U8::<A>::constant(U8::new(literal_type.type_id())),
555 next_bits(expected_size as usize)?,
556 );
557 Ok(circuit::Plaintext::from(literal))
558 }
559 PlaintextType::Struct(identifier) => {
560 let struct_ = get_struct(identifier)?;
562 deserialize_struct(&struct_)
563 }
564 PlaintextType::ExternalStruct(_identifier) => {
565 let struct_ = get_external_struct(_identifier)?;
567 deserialize_struct(&struct_)
568 }
569 PlaintextType::Array(array_type) => {
570 let expected_length = **array_type.length();
572
573 if variant == (DeserializeVariant::FromBits as u8) {
575 let plaintext_variant = next_bits(2)?;
576 let expected_bits = PlaintextType::<A::Network>::ARRAY_PREFIX_BITS.map(circuit::Boolean::<A>::constant);
577 A::assert_eq(&expected_bits[0], &plaintext_variant[0]);
578 A::assert_eq(&expected_bits[1], &plaintext_variant[1]);
579
580 let num_elements = circuit::U32::<A>::from_bits_le(next_bits(32)?);
581 A::assert_eq(&num_elements, circuit::U32::<A>::constant(U32::new(expected_length)));
582 }
583
584 let expected_element_type = array_type.next_element_type();
585 let expected_element_size = u16::try_from(get_size_in_bits(expected_element_type)?)
586 .map_err(|_| anyhow!("Element size exceeds maximum of 65535 bits."))?;
587
588 let mut elements = Vec::with_capacity(expected_length as usize);
589
590 for _ in 0..**array_type.length() {
591 if variant == (DeserializeVariant::FromBits as u8) {
592 let element_size = circuit::U16::<A>::from_bits_le(next_bits(16)?);
593 A::assert_eq(&element_size, circuit::U16::<A>::constant(U16::new(expected_element_size)));
594 }
595
596 let element = execute_deserialize_internal(
597 variant,
598 next_bits(expected_element_size as usize)?,
599 expected_element_type,
600 get_struct,
601 get_external_struct,
602 depth + 1,
603 )?;
604 elements.push(element);
605 }
606
607 Ok(circuit::Plaintext::Array(elements, Default::default()))
609 }
610 }
611}
612
613impl<N: Network, const VARIANT: u8> DeserializeInstruction<N, VARIANT> {
614 pub fn evaluate(&self, stack: &impl StackTrait<N>, registers: &mut impl RegistersTrait<N>) -> Result<()> {
616 check_number_of_operands(VARIANT, self.operands.len())?;
618 check_operand_type_is_valid(VARIANT, &self.operand_type)?;
620 check_destination_type_is_valid(VARIANT, &self.destination_type)?;
622
623 let input = registers.load(stack, &self.operands[0])?;
625
626 let bits = match input {
628 Value::Plaintext(plaintext) => {
629 plaintext.as_bit_array()?
631 }
632 _ => bail!("Expected input to be a plaintext bit array"),
633 };
634
635 let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
637
638 let get_external_struct = |locator: &Locator<N>| {
640 stack.get_external_stack(locator.program_id())?.program().get_struct(locator.resource()).cloned()
641 };
642
643 let size_in_bits = match VARIANT {
645 0 => self.destination_type.size_in_bits(&get_struct, &get_external_struct)?,
646 1 => self.destination_type.size_in_bits_raw(&get_struct, &get_external_struct)?,
647 variant => bail!("Invalid `deserialize` variant '{variant}'"),
648 };
649
650 ensure!(
652 bits.len() == size_in_bits as usize,
653 "The number of bits of the operand '{}' does not match the destination '{size_in_bits}'",
654 bits.len()
655 );
656
657 let output = evaluate_deserialize_internal(
659 VARIANT,
660 &bits,
661 &self.destination_type,
662 &get_struct,
663 &get_external_struct,
664 0,
665 )?;
666
667 registers.store(stack, &self.destination, Value::Plaintext(output))
669 }
670
671 pub fn execute<A: circuit::Aleo<Network = N>>(
673 &self,
674 stack: &impl StackTrait<N>,
675 registers: &mut impl RegistersCircuit<N, A>,
676 ) -> Result<()> {
677 check_number_of_operands(VARIANT, self.operands.len())?;
679 check_operand_type_is_valid(VARIANT, &self.operand_type)?;
681 check_destination_type_is_valid(VARIANT, &self.destination_type)?;
683
684 let input = registers.load_circuit(stack, &self.operands[0])?;
686
687 let bits = match input {
689 circuit::Value::Plaintext(plaintext) => plaintext.as_bit_array()?,
690 _ => bail!("Expected input to be a plaintext"),
691 };
692
693 let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
695
696 let get_external_struct = |locator: &Locator<N>| {
698 stack.get_external_stack(locator.program_id())?.program().get_struct(locator.resource()).cloned()
699 };
700
701 let size_in_bits = match VARIANT {
703 0 => self.destination_type.size_in_bits(&get_struct, &get_external_struct)?,
704 1 => self.destination_type.size_in_bits_raw(&get_struct, &get_external_struct)?,
705 variant => bail!("Invalid `deserialize` variant '{variant}'"),
706 };
707
708 ensure!(
710 bits.len() == size_in_bits as usize,
711 "The number of bits of the operand '{}' does not match the destination '{size_in_bits}'",
712 bits.len()
713 );
714
715 let output =
717 execute_deserialize_internal(VARIANT, &bits, &self.destination_type, &get_struct, &get_external_struct, 0)?;
718
719 registers.store_circuit(stack, &self.destination, circuit::Value::Plaintext(output))
721 }
722
723 #[inline]
725 pub fn finalize(&self, stack: &impl StackTrait<N>, registers: &mut impl RegistersTrait<N>) -> Result<()> {
726 self.evaluate(stack, registers)
727 }
728
729 pub fn output_types(
731 &self,
732 stack: &impl StackTrait<N>,
733 input_types: &[RegisterType<N>],
734 ) -> Result<Vec<RegisterType<N>>> {
735 check_number_of_operands(VARIANT, self.operands.len())?;
737 check_operand_type_is_valid(VARIANT, &self.operand_type)?;
739 check_destination_type_is_valid(VARIANT, &self.destination_type)?;
741
742 ensure!(input_types.len() == 1, "Expected exactly one input type");
744 match &input_types[0] {
745 RegisterType::Plaintext(PlaintextType::Array(array_type)) if array_type == &self.operand_type => {}
746 _ => bail!("Input type {:?} does not match operand type {:?}", input_types[0], self.operand_type),
747 }
748
749 let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
751
752 let get_external_struct = |locator: &Locator<N>| {
754 stack.get_external_stack(locator.program_id())?.program().get_struct(locator.resource()).cloned()
755 };
756
757 let size_in_bits = match VARIANT {
759 0 => self.destination_type.size_in_bits(&get_struct, &get_external_struct)?,
760 1 => self.destination_type.size_in_bits_raw(&get_struct, &get_external_struct)?,
761 variant => bail!("Invalid `deserialize` variant '{variant}'"),
762 };
763
764 ensure!(
766 **self.operand_type.length() as usize == size_in_bits,
767 "The number of bits of the operand '{}' does not match the destination '{size_in_bits}'",
768 **self.operand_type.length()
769 );
770
771 Ok(vec![RegisterType::Plaintext(self.destination_type.clone())])
772 }
773}
774
775impl<N: Network, const VARIANT: u8> Parser for DeserializeInstruction<N, VARIANT> {
776 fn parse(string: &str) -> ParserResult<Self> {
778 fn parse_operands<N: Network>(string: &str, num_operands: usize) -> ParserResult<Vec<Operand<N>>> {
780 let mut operands = Vec::with_capacity(num_operands);
781 let mut string = string;
782
783 for _ in 0..num_operands {
784 let (next_string, _) = Sanitizer::parse_whitespaces(string)?;
786 let (next_string, operand) = Operand::parse(next_string)?;
788 string = next_string;
790 operands.push(operand);
792 }
793
794 Ok((string, operands))
795 }
796
797 let (string, _) = tag(*Self::opcode())(string)?;
799 let (string, operands) = parse_operands(string, 1)?;
801
802 let (string, _) = Sanitizer::parse_whitespaces(string)?;
804 let (string, _) = tag("(")(string)?;
806 let (string, _) = Sanitizer::parse_whitespaces(string)?;
808 let (string, operand_type) = ArrayType::parse(string)?;
810 let (string, _) = tag(")")(string)?;
812
813 let (string, _) = Sanitizer::parse_whitespaces(string)?;
815 let (string, _) = tag("into")(string)?;
817 let (string, _) = Sanitizer::parse_whitespaces(string)?;
819 let (string, destination) = Register::parse(string)?;
821
822 let (string, _) = Sanitizer::parse_whitespaces(string)?;
824 let (string, _) = tag("(")(string)?;
826 let (string, _) = Sanitizer::parse_whitespaces(string)?;
828 let (string, destination_type) = PlaintextType::parse(string)?;
830 let (string, _) = tag(")")(string)?;
832
833 match Self::new(operands, operand_type, destination, destination_type) {
835 Ok(instruction) => Ok((string, instruction)),
836 Err(e) => map_res(fail, |_: ParserResult<Self>| {
837 Err(error(format!("Failed to parse '{}' instruction: {e}", Self::opcode())))
838 })(string),
839 }
840 }
841}
842
843impl<N: Network, const VARIANT: u8> FromStr for DeserializeInstruction<N, VARIANT> {
844 type Err = Error;
845
846 fn from_str(string: &str) -> Result<Self> {
848 match Self::parse(string) {
849 Ok((remainder, object)) => {
850 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
852 Ok(object)
854 }
855 Err(error) => bail!("Failed to parse string. {error}"),
856 }
857 }
858}
859
860impl<N: Network, const VARIANT: u8> Debug for DeserializeInstruction<N, VARIANT> {
861 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
863 Display::fmt(self, f)
864 }
865}
866
867impl<N: Network, const VARIANT: u8> Display for DeserializeInstruction<N, VARIANT> {
868 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
870 write!(f, "{} ", Self::opcode())?;
871 self.operands.iter().try_for_each(|operand| write!(f, "{operand} "))?;
872 write!(f, " ({}) into {} ({})", self.operand_type, self.destination, self.destination_type)
873 }
874}
875
876impl<N: Network, const VARIANT: u8> FromBytes for DeserializeInstruction<N, VARIANT> {
877 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
879 let operand = Operand::read_le(&mut reader)?;
881 let operand_type = ArrayType::read_le(&mut reader)?;
883 let destination = Register::read_le(&mut reader)?;
885 let destination_type = PlaintextType::read_le(&mut reader)?;
887 match Self::new(vec![operand], operand_type, destination, destination_type) {
889 Ok(instruction) => Ok(instruction),
890 Err(e) => Err(error(format!("Failed to read '{}' instruction: {e}", Self::opcode()))),
891 }
892 }
893}
894
895impl<N: Network, const VARIANT: u8> ToBytes for DeserializeInstruction<N, VARIANT> {
896 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
898 self.operands.iter().try_for_each(|operand| operand.write_le(&mut writer))?;
900 self.operand_type.write_le(&mut writer)?;
902 self.destination.write_le(&mut writer)?;
904 self.destination_type.write_le(&mut writer)
906 }
907}
908
909#[cfg(test)]
910mod tests {
911 use super::*;
912 use console::{network::MainnetV0, types::U32};
913
914 type CurrentNetwork = MainnetV0;
915
916 fn valid_destination_types<N: Network>() -> &'static [PlaintextType<N>] {
918 &[
919 PlaintextType::Literal(LiteralType::Address),
920 PlaintextType::Literal(LiteralType::Field),
921 PlaintextType::Literal(LiteralType::Group),
922 PlaintextType::Literal(LiteralType::I8),
923 PlaintextType::Literal(LiteralType::I16),
924 PlaintextType::Literal(LiteralType::I32),
925 PlaintextType::Literal(LiteralType::I64),
926 PlaintextType::Literal(LiteralType::I128),
927 PlaintextType::Literal(LiteralType::U8),
928 PlaintextType::Literal(LiteralType::U16),
929 PlaintextType::Literal(LiteralType::U32),
930 PlaintextType::Literal(LiteralType::U64),
931 PlaintextType::Literal(LiteralType::U128),
932 PlaintextType::Literal(LiteralType::Scalar),
933 ]
934 }
935
936 fn sample_source_type<N: Network, const VARIANT: u8>(rng: &mut TestRng) -> ArrayType<N> {
938 let array_length = 1 + (u32::rand(rng) % u32::try_from(N::MAX_ARRAY_ELEMENTS).unwrap());
940 match VARIANT {
941 0 | 1 => {
942 ArrayType::new(PlaintextType::Literal(LiteralType::Boolean), vec![U32::new(array_length)]).unwrap()
943 }
944 _ => panic!("Invalid variant"),
945 }
946 }
947
948 fn run_parser_test<const VARIANT: u8>(rng: &mut TestRng) {
949 for destination_type in valid_destination_types::<CurrentNetwork>() {
950 {
951 let opcode = DeserializeVariant::opcode(VARIANT);
952 let source_type = sample_source_type::<CurrentNetwork, VARIANT>(rng);
953 let instruction = format!("{opcode} r0 ({source_type}) into r1 ({destination_type})",);
954 println!("Parsing instruction: '{instruction}'");
955
956 let (string, deserialize) =
957 DeserializeInstruction::<CurrentNetwork, VARIANT>::parse(&instruction).unwrap();
958 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
959 assert_eq!(deserialize.operands.len(), 1, "The number of operands is incorrect");
960 assert_eq!(
961 deserialize.operands[0],
962 Operand::Register(Register::Locator(0)),
963 "The first operand is incorrect"
964 );
965 assert_eq!(&deserialize.operand_type, &source_type, "The operand type is incorrect");
966 assert_eq!(deserialize.destination, Register::Locator(1), "The destination register is incorrect");
967 assert_eq!(&deserialize.destination_type, destination_type, "The destination type is incorrect");
968 }
969 }
970 }
971
972 #[test]
973 fn test_parse() {
974 let rng = &mut TestRng::default();
976
977 run_parser_test::<{ DeserializeVariant::FromBits as u8 }>(rng);
979 run_parser_test::<{ DeserializeVariant::FromBitsRaw as u8 }>(rng);
980 }
981}