Skip to main content

snarkvm_synthesizer_program/logic/instruction/operation/
deserialize.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use 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
39/// Deserializes the bits into a value.
40pub type DeserializeBits<N> = DeserializeInstruction<N, { DeserializeVariant::FromBits as u8 }>;
41/// Deserializes the raw bits into a value.
42pub type DeserializeBitsRaw<N> = DeserializeInstruction<N, { DeserializeVariant::FromBitsRaw as u8 }>;
43
44/// The deserialization variant.
45#[derive(Debug, Clone, Eq, PartialEq)]
46pub enum DeserializeVariant {
47    FromBits,
48    FromBitsRaw,
49}
50
51impl DeserializeVariant {
52    // Returns the opcode associated with the variant.
53    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    // Returns the variant, given a `u8`.
62    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
71/// Checks that the number of operands is correct.
72fn 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
79/// Checks that the operand type is valid.
80fn 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
89/// Check that the destination type is valid.
90fn check_destination_type_is_valid(variant: u8, destination_type: &PlaintextType<impl Network>) -> Result<()> {
91    // A helper function to check a literal type.
92    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/// Deserializes the operand into the declared type.
127#[derive(Clone, PartialEq, Eq, Hash)]
128pub struct DeserializeInstruction<N: Network, const VARIANT: u8> {
129    /// The operand as `input`.
130    operands: Vec<Operand<N>>,
131    /// The operand type.
132    operand_type: ArrayType<N>,
133    /// The destination register.
134    destination: Register<N>,
135    /// The destination register type.
136    destination_type: PlaintextType<N>,
137}
138
139impl<N: Network, const VARIANT: u8> DeserializeInstruction<N, VARIANT> {
140    /// Initializes a new `deserialize` instruction.
141    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        // Sanity check the number of operands.
148        check_number_of_operands(VARIANT, operands.len())?;
149        // Ensure that the operand type is valid.
150        check_operand_type_is_valid(VARIANT, &operand_type)?;
151        // Sanity check the destination type.
152        check_destination_type_is_valid(VARIANT, &destination_type)?;
153        // Return the instruction.
154        Ok(Self { operands, operand_type, destination, destination_type })
155    }
156
157    /// Returns the opcode.
158    pub const fn opcode() -> Opcode {
159        Opcode::Deserialize(DeserializeVariant::opcode(VARIANT))
160    }
161
162    /// Returns the operands in the operation.
163    pub fn operands(&self) -> &[Operand<N>] {
164        // Sanity check that the operands is the correct length.
165        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        // Return the operand.
171        &self.operands
172    }
173
174    /// Returns the operand type.
175    pub const fn operand_type(&self) -> &ArrayType<N> {
176        &self.operand_type
177    }
178
179    /// Returns the destination register.
180    #[inline]
181    pub fn destinations(&self) -> Vec<Register<N>> {
182        vec![self.destination.clone()]
183    }
184
185    /// Returns the destination register type.
186    #[inline]
187    pub const fn destination_type(&self) -> &PlaintextType<N> {
188        &self.destination_type
189    }
190
191    /// Returns whether this instruction refers to an external struct.
192    #[inline]
193    pub fn contains_external_struct(&self) -> bool {
194        self.destination_type.contains_external_struct()
195    }
196}
197
198/// Evaluate a `deserialize` operation.
199///
200/// This allows running `deserialize` without the machinery of stacks and registers.
201/// This is necessary for the Leo interpreter.
202pub 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    // Ensure that the depth is within the maximum limit.
229    if depth > N::MAX_DATA_DEPTH {
230        bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH)
231    }
232
233    // A helper to get the number of bits needed.
234    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    // Get the number of bits needed.
242    let size_in_bits = get_size_in_bits(destination_type)?;
243
244    // Check that the number of bits is correct.
245    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    // The starting index used to create subsequent subslices of the `bits` slice.
253    let mut index = 0;
254
255    // Helper function to get the next n bits as a slice.
256    let mut next_bits = |n: usize| -> Result<&[bool]> {
257        // Safely procure a subslice with the length `n` starting at `index`.
258        let subslice = bits.get(index..index + n);
259        // Check if the range is within bounds.
260        if let Some(next_bits) = subslice {
261            // Move the starting index.
262            index += n;
263            // Return the subslice.
264            Ok(next_bits)
265        } else {
266            bail!("Insufficient bits");
267        }
268    };
269
270    // Closure to deserialize a struct from a resolved `StructType<N>`.
271    let mut deserialize_struct = |struct_: &StructType<N>| -> Result<Plaintext<N>> {
272        // If the variant is `FromBits`, check the variant and metadata.
273        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        // Get the members.
286        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            // Get the expected size of the literal.
334            let expected_size = literal_type.size_in_bits::<N>();
335
336            // If the variant is `FromBits`, check the variant and metadata.
337            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            // Deserialize the literal.
358            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            // Get the struct.
363            let struct_ = get_struct(identifier)?;
364            deserialize_struct(&struct_)
365        }
366        PlaintextType::ExternalStruct(locator) => {
367            // Get the external struct.
368            let struct_ = get_external_struct(locator)?;
369            deserialize_struct(&struct_)
370        }
371        PlaintextType::Array(array_type) => {
372            // If the variant is `FromBits`, check the variant and metadata.
373            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            // Cache the plaintext bits, and return the array.
415            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    // Ensure that the depth is within the maximum limit.
435    if depth > A::Network::MAX_DATA_DEPTH {
436        bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH)
437    }
438
439    // A helper to get the number of bits needed.
440    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    // Get the number of bits needed.
448    let size_in_bits = get_size_in_bits(destination_type)?;
449
450    // Check that the number of bits is correct.
451    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    // The starting index used to create subsequent subslices of the `bits` slice.
459    let mut index = 0;
460
461    // Helper function to get the next n bits as a slice.
462    let mut next_bits = |n: usize| -> Result<&[circuit::Boolean<A>]> {
463        // Safely procure a subslice with the length `n` starting at `index`.
464        let subslice = bits.get(index..index + n);
465        // Check if the range is within bounds.
466        if let Some(next_bits) = subslice {
467            // Move the starting index.
468            index += n;
469            // Return the subslice.
470            Ok(next_bits)
471        } else {
472            bail!("Insufficient bits");
473        }
474    };
475
476    // Closure to deserialize a struct from a resolved `StructType<N>`.
477    let mut deserialize_struct = |struct_: &StructType<N>| -> Result<circuit::Plaintext<A>> {
478        // Get the expected number of members.
479        let expected_num_members =
480            u8::try_from(struct_.members().len()).map_err(|_| anyhow!("Struct exceeds maximum of entries."))?;
481
482        // If the variant is `FromBits`, check the variant and metadata.
483        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        // Get the members.
494        let mut members = IndexMap::with_capacity(struct_.members().len());
495
496        for (member_identifier, member_type) in struct_.members().iter() {
497            // Get the expected member size.
498            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 the variant is `FromBits`, check the member metadata.
502            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        // Cache the plaintext bits, and return the struct.
530        Ok(circuit::Plaintext::Struct(members, Default::default()))
531    };
532
533    match destination_type {
534        PlaintextType::Literal(literal_type) => {
535            // Get the expected size of the literal.
536            let expected_size = literal_type.size_in_bits::<A::Network>();
537
538            // If the variant is `FromBits`, check the variant and metadata.
539            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            // Deserialize the literal.
553            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            // Get the struct.
561            let struct_ = get_struct(identifier)?;
562            deserialize_struct(&struct_)
563        }
564        PlaintextType::ExternalStruct(_identifier) => {
565            // Get the external struct.
566            let struct_ = get_external_struct(_identifier)?;
567            deserialize_struct(&struct_)
568        }
569        PlaintextType::Array(array_type) => {
570            // Get the expected length of the array.
571            let expected_length = **array_type.length();
572
573            // If the variant is `FromBits`, check the variant and metadata.
574            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            // Cache the plaintext bits, and return the array.
608            Ok(circuit::Plaintext::Array(elements, Default::default()))
609        }
610    }
611}
612
613impl<N: Network, const VARIANT: u8> DeserializeInstruction<N, VARIANT> {
614    /// Evaluates the instruction.
615    pub fn evaluate(&self, stack: &impl StackTrait<N>, registers: &mut impl RegistersTrait<N>) -> Result<()> {
616        // Ensure the number of operands is correct.
617        check_number_of_operands(VARIANT, self.operands.len())?;
618        // Ensure that the operand type is valid.
619        check_operand_type_is_valid(VARIANT, &self.operand_type)?;
620        // Ensure the destination type is valid.
621        check_destination_type_is_valid(VARIANT, &self.destination_type)?;
622
623        // Load the operand.
624        let input = registers.load(stack, &self.operands[0])?;
625
626        // Get the bits of the operand.
627        let bits = match input {
628            Value::Plaintext(plaintext) => {
629                // Get the plaintext as a bit array.
630                plaintext.as_bit_array()?
631            }
632            _ => bail!("Expected input to be a plaintext bit array"),
633        };
634
635        // A helper to get a struct declaration.
636        let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
637
638        // A helper to get an external struct declaration.
639        let get_external_struct = |locator: &Locator<N>| {
640            stack.get_external_stack(locator.program_id())?.program().get_struct(locator.resource()).cloned()
641        };
642
643        // Get the size in bits of the operand.
644        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        // Check that the number of bits matches the desired length.
651        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        // Deserialize into the desired output.
658        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        // Store the output.
668        registers.store(stack, &self.destination, Value::Plaintext(output))
669    }
670
671    /// Executes the instruction.
672    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        // Ensure the number of operands is correct.
678        check_number_of_operands(VARIANT, self.operands.len())?;
679        // Ensure that the operand type is valid.
680        check_operand_type_is_valid(VARIANT, &self.operand_type)?;
681        // Ensure the destination type is valid.
682        check_destination_type_is_valid(VARIANT, &self.destination_type)?;
683
684        // Load the operand.
685        let input = registers.load_circuit(stack, &self.operands[0])?;
686
687        // Get the input as a bit array.
688        let bits = match input {
689            circuit::Value::Plaintext(plaintext) => plaintext.as_bit_array()?,
690            _ => bail!("Expected input to be a plaintext"),
691        };
692
693        // A helper to get a struct declaration.
694        let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
695
696        // A helper to get an external struct declaration.
697        let get_external_struct = |locator: &Locator<N>| {
698            stack.get_external_stack(locator.program_id())?.program().get_struct(locator.resource()).cloned()
699        };
700
701        // Get the size in bits of the operand.
702        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        // Check that the number of bits matches the desired length.
709        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        // Deserialize the bits into the desired literal type.
716        let output =
717            execute_deserialize_internal(VARIANT, &bits, &self.destination_type, &get_struct, &get_external_struct, 0)?;
718
719        // Store the output.
720        registers.store_circuit(stack, &self.destination, circuit::Value::Plaintext(output))
721    }
722
723    /// Finalizes the instruction.
724    #[inline]
725    pub fn finalize(&self, stack: &impl StackTrait<N>, registers: &mut impl RegistersTrait<N>) -> Result<()> {
726        self.evaluate(stack, registers)
727    }
728
729    /// Returns the output type from the given program and input types.
730    pub fn output_types(
731        &self,
732        stack: &impl StackTrait<N>,
733        input_types: &[RegisterType<N>],
734    ) -> Result<Vec<RegisterType<N>>> {
735        // Ensure the number of operands is correct.
736        check_number_of_operands(VARIANT, self.operands.len())?;
737        // Ensure the operand type is valid.
738        check_operand_type_is_valid(VARIANT, &self.operand_type)?;
739        // Ensure the destination type is valid.
740        check_destination_type_is_valid(VARIANT, &self.destination_type)?;
741
742        // Check that the input type matches the operand type.
743        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        // A helper to get a struct declaration.
750        let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
751
752        // A helper to get an external struct declaration.
753        let get_external_struct = |locator: &Locator<N>| {
754            stack.get_external_stack(locator.program_id())?.program().get_struct(locator.resource()).cloned()
755        };
756
757        // Get the size in bits of the operand.
758        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        // Check that the number of bits of the operand matches the destination.
765        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    /// Parses a string into an operation.
777    fn parse(string: &str) -> ParserResult<Self> {
778        /// Parse the operands from the string.
779        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                // Parse the whitespace from the string.
785                let (next_string, _) = Sanitizer::parse_whitespaces(string)?;
786                // Parse the operand from the string.
787                let (next_string, operand) = Operand::parse(next_string)?;
788                // Update the string.
789                string = next_string;
790                // Push the operand.
791                operands.push(operand);
792            }
793
794            Ok((string, operands))
795        }
796
797        // Parse the opcode from the string.
798        let (string, _) = tag(*Self::opcode())(string)?;
799        // Parse the operands from the string.
800        let (string, operands) = parse_operands(string, 1)?;
801
802        // Parse the whitespace from the string.
803        let (string, _) = Sanitizer::parse_whitespaces(string)?;
804        // Parse the "(" from the string.
805        let (string, _) = tag("(")(string)?;
806        // Parse the whitespace from the string.
807        let (string, _) = Sanitizer::parse_whitespaces(string)?;
808        // Parse the operand type from the string.
809        let (string, operand_type) = ArrayType::parse(string)?;
810        // Parse the ")" from the string.
811        let (string, _) = tag(")")(string)?;
812
813        // Parse the whitespace from the string.
814        let (string, _) = Sanitizer::parse_whitespaces(string)?;
815        // Parse the "into" from the string.
816        let (string, _) = tag("into")(string)?;
817        // Parse the whitespace from the string.
818        let (string, _) = Sanitizer::parse_whitespaces(string)?;
819        // Parse the destination register from the string.
820        let (string, destination) = Register::parse(string)?;
821
822        // Parse the whitespace from the string.
823        let (string, _) = Sanitizer::parse_whitespaces(string)?;
824        // Parse the "(" from the string.
825        let (string, _) = tag("(")(string)?;
826        // Parse the whitespace from the string.
827        let (string, _) = Sanitizer::parse_whitespaces(string)?;
828        // Parse the destination register type from the string.
829        let (string, destination_type) = PlaintextType::parse(string)?;
830        // Parse the ")" from the string.
831        let (string, _) = tag(")")(string)?;
832
833        // Construct the instruction, checking for errors.
834        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    /// Parses a string into an operation.
847    fn from_str(string: &str) -> Result<Self> {
848        match Self::parse(string) {
849            Ok((remainder, object)) => {
850                // Ensure the remainder is empty.
851                ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
852                // Return the object.
853                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    /// Prints the operation as a string.
862    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    /// Prints the operation to a string.
869    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    /// Reads the operation from a buffer.
878    fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
879        // Read the operand.
880        let operand = Operand::read_le(&mut reader)?;
881        // Read the operand type.
882        let operand_type = ArrayType::read_le(&mut reader)?;
883        // Read the destination register.
884        let destination = Register::read_le(&mut reader)?;
885        // Read the destination register type.
886        let destination_type = PlaintextType::read_le(&mut reader)?;
887        // Return the operation.
888        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    /// Writes the operation to a buffer.
897    fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
898        // Write the operands.
899        self.operands.iter().try_for_each(|operand| operand.write_le(&mut writer))?;
900        // Write the operand type.
901        self.operand_type.write_le(&mut writer)?;
902        // Write the destination register.
903        self.destination.write_le(&mut writer)?;
904        // Write the destination register type.
905        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    /// **Attention**: When changing this, also update in `tests/instruction/deserialize.rs`.
917    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    /// Randomly sample a source type.
937    fn sample_source_type<N: Network, const VARIANT: u8>(rng: &mut TestRng) -> ArrayType<N> {
938        // Generate a random array length between 1 and N::MAX_ARRAY_ELEMENTS.
939        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        // Initialize an RNG.
975        let rng = &mut TestRng::default();
976
977        // Run the parser test for each variant.
978        run_parser_test::<{ DeserializeVariant::FromBits as u8 }>(rng);
979        run_parser_test::<{ DeserializeVariant::FromBitsRaw as u8 }>(rng);
980    }
981}