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
109 | LiteralType::Identifier => Ok(()),
110 _ => bail!("Invalid literal type '{literal_type}' for 'deserialize' instruction"),
111 }
112 }
113
114 match destination_type {
115 PlaintextType::Literal(literal_type) => check_literal_type(literal_type),
116 PlaintextType::Array(array_type) => match array_type.base_element_type() {
117 PlaintextType::Literal(literal_type) => check_literal_type(literal_type),
118 _ => bail!("Invalid element type '{array_type}' for 'deserialize' instruction"),
119 },
120 _ => bail!(
121 "Instruction '{}' cannot take type '{destination_type}' as input",
122 DeserializeVariant::opcode(variant)
123 ),
124 }
125}
126
127#[derive(Clone, PartialEq, Eq, Hash)]
129pub struct DeserializeInstruction<N: Network, const VARIANT: u8> {
130 operands: Vec<Operand<N>>,
132 operand_type: ArrayType<N>,
134 destination: Register<N>,
136 destination_type: PlaintextType<N>,
138}
139
140impl<N: Network, const VARIANT: u8> DeserializeInstruction<N, VARIANT> {
141 pub fn new(
143 operands: Vec<Operand<N>>,
144 operand_type: ArrayType<N>,
145 destination: Register<N>,
146 destination_type: PlaintextType<N>,
147 ) -> Result<Self> {
148 check_number_of_operands(VARIANT, operands.len())?;
150 check_operand_type_is_valid(VARIANT, &operand_type)?;
152 check_destination_type_is_valid(VARIANT, &destination_type)?;
154 Ok(Self { operands, operand_type, destination, destination_type })
156 }
157
158 pub const fn opcode() -> Opcode {
160 Opcode::Deserialize(DeserializeVariant::opcode(VARIANT))
161 }
162
163 pub fn operands(&self) -> &[Operand<N>] {
165 if cfg!(debug_assertions) {
167 check_number_of_operands(VARIANT, self.operands.len()).unwrap();
168 check_operand_type_is_valid(VARIANT, &self.operand_type).unwrap();
169 check_destination_type_is_valid(VARIANT, &self.destination_type).unwrap();
170 }
171 &self.operands
173 }
174
175 pub const fn operand_type(&self) -> &ArrayType<N> {
177 &self.operand_type
178 }
179
180 #[inline]
182 pub fn destinations(&self) -> Vec<Register<N>> {
183 vec![self.destination.clone()]
184 }
185
186 #[inline]
188 pub const fn destination_type(&self) -> &PlaintextType<N> {
189 &self.destination_type
190 }
191
192 #[inline]
194 pub fn contains_external_struct(&self) -> bool {
195 self.destination_type.contains_external_struct()
196 }
197}
198
199pub fn evaluate_deserialize<N: Network, F0, F1>(
204 variant: DeserializeVariant,
205 bits: &[bool],
206 destination_type: &PlaintextType<N>,
207 get_struct: &F0,
208 get_external_struct: &F1,
209) -> Result<Plaintext<N>>
210where
211 F0: Fn(&Identifier<N>) -> Result<StructType<N>>,
212 F1: Fn(&Locator<N>) -> Result<StructType<N>>,
213{
214 evaluate_deserialize_internal(variant as u8, bits, destination_type, get_struct, get_external_struct, 0)
215}
216
217fn evaluate_deserialize_internal<N: Network, F0, F1>(
218 variant: u8,
219 bits: &[bool],
220 destination_type: &PlaintextType<N>,
221 get_struct: &F0,
222 get_external_struct: &F1,
223 depth: usize,
224) -> Result<Plaintext<N>>
225where
226 F0: Fn(&Identifier<N>) -> Result<StructType<N>>,
227 F1: Fn(&Locator<N>) -> Result<StructType<N>>,
228{
229 if depth > N::MAX_DATA_DEPTH {
231 bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH)
232 }
233
234 let get_size_in_bits = |plaintext_type: &PlaintextType<N>| -> Result<usize> {
236 match DeserializeVariant::from_u8(variant) {
237 DeserializeVariant::FromBits => plaintext_type.size_in_bits(get_struct, &get_external_struct),
238 DeserializeVariant::FromBitsRaw => plaintext_type.size_in_bits_raw(get_struct, &get_external_struct),
239 }
240 };
241
242 let size_in_bits = get_size_in_bits(destination_type)?;
244
245 let bits = bits.to_vec();
247 ensure!(
248 bits.len() == size_in_bits,
249 "The number of bits of the operand '{}' does not match the destination '{size_in_bits}'",
250 bits.len()
251 );
252
253 let mut index = 0;
255
256 let mut next_bits = |n: usize| -> Result<&[bool]> {
258 let subslice = bits.get(index..index + n);
260 if let Some(next_bits) = subslice {
262 index += n;
264 Ok(next_bits)
266 } else {
267 bail!("Insufficient bits");
268 }
269 };
270
271 let mut deserialize_struct = |struct_: &StructType<N>| -> Result<Plaintext<N>> {
273 if variant == (DeserializeVariant::FromBits as u8) {
275 let plaintext_variant = next_bits(2)?;
276 let plaintext_variant = [plaintext_variant[0], plaintext_variant[1]];
277 ensure!(
278 plaintext_variant == PlaintextType::<N>::STRUCT_PREFIX_BITS,
279 "Invalid plaintext variant for struct type"
280 );
281
282 let num_members = u8::from_bits_le(next_bits(8)?)?;
283 ensure!(struct_.members().len() == num_members as usize, "Struct exceeds maximum of entries.");
284 }
285
286 let mut members = IndexMap::with_capacity(struct_.members().len());
288
289 for (member_identifier, member_type) in struct_.members().iter() {
290 let expected_member_size = get_size_in_bits(member_type)?;
291
292 if variant == (DeserializeVariant::FromBits as u8) {
293 let identifier_size = u8::from_bits_le(next_bits(8)?)?;
294 ensure!(
295 member_identifier.size_in_bits() == identifier_size,
296 "Mismatched identifier size. Expected '{}', found '{}'",
297 member_identifier.size_in_bits(),
298 identifier_size
299 );
300
301 let identifier_bits = next_bits(identifier_size as usize)?;
302 let identifier = Identifier::<N>::from_bits_le(identifier_bits)?;
303 ensure!(
304 *member_identifier == identifier,
305 "Mismatched identifier. Expected '{member_identifier}', found '{identifier}'",
306 );
307
308 let member_size = u16::from_bits_le(next_bits(16)?)?;
309 ensure!(
310 member_size as usize == expected_member_size,
311 "Mismatched member size. Expected '{expected_member_size}', found '{member_size}'",
312 );
313 }
314
315 let value = evaluate_deserialize_internal(
316 variant,
317 next_bits(expected_member_size)?,
318 member_type,
319 get_struct,
320 get_external_struct,
321 depth + 1,
322 )?;
323
324 if members.insert(*member_identifier, value).is_some() {
325 bail!("Duplicate identifier in struct.");
326 }
327 }
328
329 Ok(Plaintext::Struct(members, Default::default()))
330 };
331
332 match destination_type {
333 PlaintextType::Literal(literal_type) => {
334 let expected_size = literal_type.size_in_bits::<N>();
336
337 if variant == (DeserializeVariant::FromBits as u8) {
339 let plaintext_variant = next_bits(2)?;
340 let plaintext_variant = [plaintext_variant[0], plaintext_variant[1]];
341 ensure!(
342 plaintext_variant == PlaintextType::<N>::LITERAL_PREFIX_BITS,
343 "Invalid plaintext variant for literal type '{literal_type}'"
344 );
345
346 let literal_variant = u8::from_bits_le(next_bits(8)?)?;
347 ensure!(
348 literal_variant == literal_type.type_id(),
349 "Mismatched literal type. Expected '{literal_type}', found '{literal_variant}'"
350 );
351
352 let literal_size = u16::from_bits_le(next_bits(16)?)?;
353 ensure!(
354 literal_size == expected_size,
355 "Mismatched literal size. Expected '{expected_size}', found '{literal_size}'",
356 );
357 };
358 let literal = Literal::from_bits_le(literal_type.type_id(), next_bits(expected_size as usize)?)?;
360 Ok(Plaintext::Literal(literal, Default::default()))
361 }
362 PlaintextType::Struct(identifier) => {
363 let struct_ = get_struct(identifier)?;
365 deserialize_struct(&struct_)
366 }
367 PlaintextType::ExternalStruct(locator) => {
368 let struct_ = get_external_struct(locator)?;
370 deserialize_struct(&struct_)
371 }
372 PlaintextType::Array(array_type) => {
373 if variant == (DeserializeVariant::FromBits as u8) {
375 let plaintext_variant = next_bits(2)?;
376 let plaintext_variant = [plaintext_variant[0], plaintext_variant[1]];
377 ensure!(
378 plaintext_variant == PlaintextType::<N>::ARRAY_PREFIX_BITS,
379 "Invalid plaintext variant for array type"
380 );
381
382 let num_elements = u32::from_bits_le(next_bits(32)?)?;
383 ensure!(
384 **array_type.length() == num_elements,
385 "Mismatched array length. Expected '{}', found '{}'",
386 **array_type.length(),
387 num_elements
388 );
389 }
390
391 let expected_element_type = array_type.next_element_type();
392 let expected_element_size = get_size_in_bits(expected_element_type)?;
393
394 let mut elements = Vec::with_capacity(**array_type.length() as usize);
395
396 for _ in 0..**array_type.length() {
397 if variant == (DeserializeVariant::FromBits as u8) {
398 let element_size = u16::from_bits_le(next_bits(16)?)?;
399 ensure!(
400 element_size as usize == expected_element_size,
401 "Mismatched element size. Expected '{expected_element_size}', found '{element_size}'",
402 );
403 }
404 let element = evaluate_deserialize_internal(
405 variant,
406 next_bits(expected_element_size)?,
407 expected_element_type,
408 get_struct,
409 get_external_struct,
410 depth + 1,
411 )?;
412 elements.push(element);
413 }
414
415 Ok(Plaintext::Array(elements, Default::default()))
417 }
418 }
419}
420
421fn execute_deserialize_internal<A: circuit::Aleo<Network = N>, N: Network, F0, F1>(
422 variant: u8,
423 bits: &[circuit::Boolean<A>],
424 destination_type: &PlaintextType<N>,
425 get_struct: &F0,
426 get_external_struct: &F1,
427 depth: usize,
428) -> Result<circuit::Plaintext<A>>
429where
430 F0: Fn(&Identifier<N>) -> Result<StructType<N>>,
431 F1: Fn(&Locator<N>) -> Result<StructType<N>>,
432{
433 use snarkvm_circuit::{Inject, traits::FromBits};
434
435 if depth > A::Network::MAX_DATA_DEPTH {
437 bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH)
438 }
439
440 let get_size_in_bits = |plaintext_type: &PlaintextType<N>| -> Result<usize> {
442 match DeserializeVariant::from_u8(variant) {
443 DeserializeVariant::FromBits => plaintext_type.size_in_bits(get_struct, get_external_struct),
444 DeserializeVariant::FromBitsRaw => plaintext_type.size_in_bits_raw(get_struct, get_external_struct),
445 }
446 };
447
448 let size_in_bits = get_size_in_bits(destination_type)?;
450
451 let bits = bits.to_vec();
453 ensure!(
454 bits.len() == size_in_bits,
455 "The number of bits of the operand '{}' does not match the destination '{size_in_bits}'",
456 bits.len()
457 );
458
459 let mut index = 0;
461
462 let mut next_bits = |n: usize| -> Result<&[circuit::Boolean<A>]> {
464 let subslice = bits.get(index..index + n);
466 if let Some(next_bits) = subslice {
468 index += n;
470 Ok(next_bits)
472 } else {
473 bail!("Insufficient bits");
474 }
475 };
476
477 let mut deserialize_struct = |struct_: &StructType<N>| -> Result<circuit::Plaintext<A>> {
479 let expected_num_members =
481 u8::try_from(struct_.members().len()).map_err(|_| anyhow!("Struct exceeds maximum of entries."))?;
482
483 if variant == (DeserializeVariant::FromBits as u8) {
485 let plaintext_variant = next_bits(2)?;
486 let expected_bits = PlaintextType::<A::Network>::STRUCT_PREFIX_BITS.map(circuit::Boolean::<A>::constant);
487 A::assert_eq(&expected_bits[0], &plaintext_variant[0])?;
488 A::assert_eq(&expected_bits[1], &plaintext_variant[1])?;
489
490 let num_members = circuit::U8::<A>::from_bits_le(next_bits(8)?);
491 A::assert_eq(num_members, circuit::U8::<A>::constant(U8::new(expected_num_members)))?;
492 }
493
494 let mut members = IndexMap::with_capacity(struct_.members().len());
496
497 for (member_identifier, member_type) in struct_.members().iter() {
498 let expected_member_size = u16::try_from(get_size_in_bits(member_type)?)
500 .map_err(|_| anyhow!("Member size exceeds maximum of 65535 bits."))?;
501
502 if variant == (DeserializeVariant::FromBits as u8) {
504 let expected_identifier_size = member_identifier.size_in_bits();
505 let identifier_size = circuit::U8::<A>::from_bits_le(next_bits(8)?);
506 A::assert_eq(&identifier_size, circuit::U8::<A>::constant(U8::new(expected_identifier_size)))?;
507
508 let identifier_bits = next_bits(expected_identifier_size as usize)?;
509 let identifier = circuit::Identifier::<A>::from_bits_le(identifier_bits);
510 A::assert_eq(circuit::Identifier::<A>::constant(*member_identifier), &identifier)?;
511
512 let member_size = circuit::U16::<A>::from_bits_le(next_bits(16)?);
513 A::assert_eq(&member_size, circuit::U16::<A>::constant(U16::new(expected_member_size)))?;
514 }
515
516 let value = execute_deserialize_internal(
517 variant,
518 next_bits(expected_member_size as usize)?,
519 member_type,
520 get_struct,
521 get_external_struct,
522 depth + 1,
523 )?;
524
525 if members.insert(circuit::Identifier::constant(*member_identifier), value).is_some() {
526 bail!("Duplicate identifier in struct.");
527 }
528 }
529
530 Ok(circuit::Plaintext::Struct(members, Default::default()))
532 };
533
534 match destination_type {
535 PlaintextType::Literal(literal_type) => {
536 let expected_size = literal_type.size_in_bits::<A::Network>();
538
539 if variant == (DeserializeVariant::FromBits as u8) {
541 let plaintext_variant = next_bits(2)?;
542 let expected_bits =
543 PlaintextType::<A::Network>::LITERAL_PREFIX_BITS.map(circuit::Boolean::<A>::constant);
544 A::assert_eq(&expected_bits[0], &plaintext_variant[0])?;
545 A::assert_eq(&expected_bits[1], &plaintext_variant[1])?;
546
547 let literal_variant = circuit::U8::<A>::from_bits_le(next_bits(8)?);
548 A::assert_eq(&literal_variant, circuit::U8::<A>::constant(U8::new(literal_type.type_id())))?;
549
550 let literal_size = circuit::U16::<A>::from_bits_le(next_bits(16)?);
551 A::assert_eq(&literal_size, circuit::U16::<A>::constant(U16::new(expected_size)))?;
552 };
553 let literal = circuit::Literal::<A>::from_bits_le(
555 &circuit::U8::<A>::constant(U8::new(literal_type.type_id())),
556 next_bits(expected_size as usize)?,
557 );
558 Ok(circuit::Plaintext::from(literal))
559 }
560 PlaintextType::Struct(identifier) => {
561 let struct_ = get_struct(identifier)?;
563 deserialize_struct(&struct_)
564 }
565 PlaintextType::ExternalStruct(_identifier) => {
566 let struct_ = get_external_struct(_identifier)?;
568 deserialize_struct(&struct_)
569 }
570 PlaintextType::Array(array_type) => {
571 let expected_length = **array_type.length();
573
574 if variant == (DeserializeVariant::FromBits as u8) {
576 let plaintext_variant = next_bits(2)?;
577 let expected_bits = PlaintextType::<A::Network>::ARRAY_PREFIX_BITS.map(circuit::Boolean::<A>::constant);
578 A::assert_eq(&expected_bits[0], &plaintext_variant[0])?;
579 A::assert_eq(&expected_bits[1], &plaintext_variant[1])?;
580
581 let num_elements = circuit::U32::<A>::from_bits_le(next_bits(32)?);
582 A::assert_eq(&num_elements, circuit::U32::<A>::constant(U32::new(expected_length)))?;
583 }
584
585 let expected_element_type = array_type.next_element_type();
586 let expected_element_size = u16::try_from(get_size_in_bits(expected_element_type)?)
587 .map_err(|_| anyhow!("Element size exceeds maximum of 65535 bits."))?;
588
589 let mut elements = Vec::with_capacity(expected_length as usize);
590
591 for _ in 0..**array_type.length() {
592 if variant == (DeserializeVariant::FromBits as u8) {
593 let element_size = circuit::U16::<A>::from_bits_le(next_bits(16)?);
594 A::assert_eq(&element_size, circuit::U16::<A>::constant(U16::new(expected_element_size)))?;
595 }
596
597 let element = execute_deserialize_internal(
598 variant,
599 next_bits(expected_element_size as usize)?,
600 expected_element_type,
601 get_struct,
602 get_external_struct,
603 depth + 1,
604 )?;
605 elements.push(element);
606 }
607
608 Ok(circuit::Plaintext::Array(elements, Default::default()))
610 }
611 }
612}
613
614impl<N: Network, const VARIANT: u8> DeserializeInstruction<N, VARIANT> {
615 pub fn evaluate(&self, stack: &impl StackTrait<N>, registers: &mut impl RegistersTrait<N>) -> Result<()> {
617 check_number_of_operands(VARIANT, self.operands.len())?;
619 check_operand_type_is_valid(VARIANT, &self.operand_type)?;
621 check_destination_type_is_valid(VARIANT, &self.destination_type)?;
623
624 let input = registers.load(stack, &self.operands[0])?;
626
627 let bits = match input {
629 Value::Plaintext(plaintext) => {
630 plaintext.as_bit_array()?
632 }
633 _ => bail!("Expected input to be a plaintext bit array"),
634 };
635
636 let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
638
639 let get_external_struct = |locator: &Locator<N>| {
641 stack.get_external_stack(locator.program_id())?.program().get_struct(locator.resource()).cloned()
642 };
643
644 let size_in_bits = match VARIANT {
646 0 => self.destination_type.size_in_bits(&get_struct, &get_external_struct)?,
647 1 => self.destination_type.size_in_bits_raw(&get_struct, &get_external_struct)?,
648 variant => bail!("Invalid `deserialize` variant '{variant}'"),
649 };
650
651 ensure!(
653 bits.len() == size_in_bits as usize,
654 "The number of bits of the operand '{}' does not match the destination '{size_in_bits}'",
655 bits.len()
656 );
657
658 let output = evaluate_deserialize_internal(
660 VARIANT,
661 &bits,
662 &self.destination_type,
663 &get_struct,
664 &get_external_struct,
665 0,
666 )?;
667
668 registers.store(stack, &self.destination, Value::Plaintext(output))
670 }
671
672 pub fn execute<A: circuit::Aleo<Network = N>>(
674 &self,
675 stack: &impl StackTrait<N>,
676 registers: &mut impl RegistersCircuit<N, A>,
677 ) -> Result<()> {
678 check_number_of_operands(VARIANT, self.operands.len())?;
680 check_operand_type_is_valid(VARIANT, &self.operand_type)?;
682 check_destination_type_is_valid(VARIANT, &self.destination_type)?;
684
685 let input = registers.load_circuit(stack, &self.operands[0])?;
687
688 let bits = match input {
690 circuit::Value::Plaintext(plaintext) => plaintext.as_bit_array()?,
691 _ => bail!("Expected input to be a plaintext"),
692 };
693
694 let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
696
697 let get_external_struct = |locator: &Locator<N>| {
699 stack.get_external_stack(locator.program_id())?.program().get_struct(locator.resource()).cloned()
700 };
701
702 let size_in_bits = match VARIANT {
704 0 => self.destination_type.size_in_bits(&get_struct, &get_external_struct)?,
705 1 => self.destination_type.size_in_bits_raw(&get_struct, &get_external_struct)?,
706 variant => bail!("Invalid `deserialize` variant '{variant}'"),
707 };
708
709 ensure!(
711 bits.len() == size_in_bits as usize,
712 "The number of bits of the operand '{}' does not match the destination '{size_in_bits}'",
713 bits.len()
714 );
715
716 let output =
718 execute_deserialize_internal(VARIANT, &bits, &self.destination_type, &get_struct, &get_external_struct, 0)?;
719
720 registers.store_circuit(stack, &self.destination, circuit::Value::Plaintext(output))
722 }
723
724 #[inline]
726 pub fn finalize(&self, stack: &impl StackTrait<N>, registers: &mut impl RegistersTrait<N>) -> Result<()> {
727 self.evaluate(stack, registers)
728 }
729
730 pub fn output_types(
732 &self,
733 stack: &impl StackTrait<N>,
734 input_types: &[RegisterType<N>],
735 ) -> Result<Vec<RegisterType<N>>> {
736 check_number_of_operands(VARIANT, self.operands.len())?;
738 check_operand_type_is_valid(VARIANT, &self.operand_type)?;
740 check_destination_type_is_valid(VARIANT, &self.destination_type)?;
742
743 ensure!(input_types.len() == 1, "Expected exactly one input type");
745 match &input_types[0] {
746 RegisterType::Plaintext(PlaintextType::Array(array_type)) if array_type == &self.operand_type => {}
747 _ => bail!("Input type {:?} does not match operand type {:?}", input_types[0], self.operand_type),
748 }
749
750 let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
752
753 let get_external_struct = |locator: &Locator<N>| {
755 stack.get_external_stack(locator.program_id())?.program().get_struct(locator.resource()).cloned()
756 };
757
758 let size_in_bits = match VARIANT {
760 0 => self.destination_type.size_in_bits(&get_struct, &get_external_struct)?,
761 1 => self.destination_type.size_in_bits_raw(&get_struct, &get_external_struct)?,
762 variant => bail!("Invalid `deserialize` variant '{variant}'"),
763 };
764
765 ensure!(
767 **self.operand_type.length() as usize == size_in_bits,
768 "The number of bits of the operand '{}' does not match the destination '{size_in_bits}'",
769 **self.operand_type.length()
770 );
771
772 Ok(vec![RegisterType::Plaintext(self.destination_type.clone())])
773 }
774}
775
776impl<N: Network, const VARIANT: u8> Parser for DeserializeInstruction<N, VARIANT> {
777 fn parse(string: &str) -> ParserResult<Self> {
779 fn parse_operands<N: Network>(string: &str, num_operands: usize) -> ParserResult<Vec<Operand<N>>> {
781 let mut operands = Vec::with_capacity(num_operands);
782 let mut string = string;
783
784 for _ in 0..num_operands {
785 let (next_string, _) = Sanitizer::parse_whitespaces(string)?;
787 let (next_string, operand) = Operand::parse(next_string)?;
789 string = next_string;
791 operands.push(operand);
793 }
794
795 Ok((string, operands))
796 }
797
798 let (string, _) = tag(*Self::opcode())(string)?;
800 let (string, operands) = parse_operands(string, 1)?;
802
803 let (string, _) = Sanitizer::parse_whitespaces(string)?;
805 let (string, _) = tag("(")(string)?;
807 let (string, _) = Sanitizer::parse_whitespaces(string)?;
809 let (string, operand_type) = ArrayType::parse(string)?;
811 let (string, _) = tag(")")(string)?;
813
814 let (string, _) = Sanitizer::parse_whitespaces(string)?;
816 let (string, _) = tag("into")(string)?;
818 let (string, _) = Sanitizer::parse_whitespaces(string)?;
820 let (string, destination) = Register::parse(string)?;
822
823 let (string, _) = Sanitizer::parse_whitespaces(string)?;
825 let (string, _) = tag("(")(string)?;
827 let (string, _) = Sanitizer::parse_whitespaces(string)?;
829 let (string, destination_type) = PlaintextType::parse(string)?;
831 let (string, _) = tag(")")(string)?;
833
834 match Self::new(operands, operand_type, destination, destination_type) {
836 Ok(instruction) => Ok((string, instruction)),
837 Err(e) => map_res(fail, |_: ParserResult<Self>| {
838 Err(error(format!("Failed to parse '{}' instruction: {e}", Self::opcode())))
839 })(string),
840 }
841 }
842}
843
844impl<N: Network, const VARIANT: u8> FromStr for DeserializeInstruction<N, VARIANT> {
845 type Err = Error;
846
847 fn from_str(string: &str) -> Result<Self> {
849 match Self::parse(string) {
850 Ok((remainder, object)) => {
851 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
853 Ok(object)
855 }
856 Err(error) => bail!("Failed to parse string. {error}"),
857 }
858 }
859}
860
861impl<N: Network, const VARIANT: u8> Debug for DeserializeInstruction<N, VARIANT> {
862 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
864 Display::fmt(self, f)
865 }
866}
867
868impl<N: Network, const VARIANT: u8> Display for DeserializeInstruction<N, VARIANT> {
869 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
871 write!(f, "{} ", Self::opcode())?;
872 self.operands.iter().try_for_each(|operand| write!(f, "{operand} "))?;
873 write!(f, " ({}) into {} ({})", self.operand_type, self.destination, self.destination_type)
874 }
875}
876
877impl<N: Network, const VARIANT: u8> FromBytes for DeserializeInstruction<N, VARIANT> {
878 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
880 let operand = Operand::read_le(&mut reader)?;
882 let operand_type = ArrayType::read_le(&mut reader)?;
884 let destination = Register::read_le(&mut reader)?;
886 let destination_type = PlaintextType::read_le(&mut reader)?;
888 match Self::new(vec![operand], operand_type, destination, destination_type) {
890 Ok(instruction) => Ok(instruction),
891 Err(e) => Err(error(format!("Failed to read '{}' instruction: {e}", Self::opcode()))),
892 }
893 }
894}
895
896impl<N: Network, const VARIANT: u8> ToBytes for DeserializeInstruction<N, VARIANT> {
897 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
899 self.operands.iter().try_for_each(|operand| operand.write_le(&mut writer))?;
901 self.operand_type.write_le(&mut writer)?;
903 self.destination.write_le(&mut writer)?;
905 self.destination_type.write_le(&mut writer)
907 }
908}
909
910#[cfg(test)]
911mod tests {
912 use super::*;
913 use console::{network::MainnetV0, types::U32};
914
915 type CurrentNetwork = MainnetV0;
916
917 fn valid_destination_types<N: Network>() -> &'static [PlaintextType<N>] {
919 &[
920 PlaintextType::Literal(LiteralType::Address),
921 PlaintextType::Literal(LiteralType::Field),
922 PlaintextType::Literal(LiteralType::Group),
923 PlaintextType::Literal(LiteralType::I8),
924 PlaintextType::Literal(LiteralType::I16),
925 PlaintextType::Literal(LiteralType::I32),
926 PlaintextType::Literal(LiteralType::I64),
927 PlaintextType::Literal(LiteralType::I128),
928 PlaintextType::Literal(LiteralType::U8),
929 PlaintextType::Literal(LiteralType::U16),
930 PlaintextType::Literal(LiteralType::U32),
931 PlaintextType::Literal(LiteralType::U64),
932 PlaintextType::Literal(LiteralType::U128),
933 PlaintextType::Literal(LiteralType::Scalar),
934 PlaintextType::Literal(LiteralType::Identifier),
935 ]
936 }
937
938 fn sample_source_type<N: Network, const VARIANT: u8>(rng: &mut TestRng) -> ArrayType<N> {
940 let array_length = 1 + (u32::rand(rng) % u32::try_from(N::LATEST_MAX_ARRAY_ELEMENTS()).unwrap());
942 match VARIANT {
943 0 | 1 => {
944 ArrayType::new(PlaintextType::Literal(LiteralType::Boolean), vec![U32::new(array_length)]).unwrap()
945 }
946 _ => panic!("Invalid variant"),
947 }
948 }
949
950 fn run_parser_test<const VARIANT: u8>(rng: &mut TestRng) {
951 for destination_type in valid_destination_types::<CurrentNetwork>() {
952 {
953 let opcode = DeserializeVariant::opcode(VARIANT);
954 let source_type = sample_source_type::<CurrentNetwork, VARIANT>(rng);
955 let instruction = format!("{opcode} r0 ({source_type}) into r1 ({destination_type})",);
956 println!("Parsing instruction: '{instruction}'");
957
958 let (string, deserialize) =
959 DeserializeInstruction::<CurrentNetwork, VARIANT>::parse(&instruction).unwrap();
960 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
961 assert_eq!(deserialize.operands.len(), 1, "The number of operands is incorrect");
962 assert_eq!(
963 deserialize.operands[0],
964 Operand::Register(Register::Locator(0)),
965 "The first operand is incorrect"
966 );
967 assert_eq!(&deserialize.operand_type, &source_type, "The operand type is incorrect");
968 assert_eq!(deserialize.destination, Register::Locator(1), "The destination register is incorrect");
969 assert_eq!(&deserialize.destination_type, destination_type, "The destination type is incorrect");
970 }
971 }
972 }
973
974 #[test]
975 fn test_parse() {
976 let rng = &mut TestRng::default();
978
979 run_parser_test::<{ DeserializeVariant::FromBits as u8 }>(rng);
981 run_parser_test::<{ DeserializeVariant::FromBitsRaw as u8 }>(rng);
982 }
983}