Skip to main content

snarkvm_synthesizer_program/logic/instruction/operation/
deserialize.rs

1// Copyright (c) 2019-2026 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
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/// Deserializes the operand into the declared type.
128#[derive(Clone, PartialEq, Eq, Hash)]
129pub struct DeserializeInstruction<N: Network, const VARIANT: u8> {
130    /// The operand as `input`.
131    operands: Vec<Operand<N>>,
132    /// The operand type.
133    operand_type: ArrayType<N>,
134    /// The destination register.
135    destination: Register<N>,
136    /// The destination register type.
137    destination_type: PlaintextType<N>,
138}
139
140impl<N: Network, const VARIANT: u8> DeserializeInstruction<N, VARIANT> {
141    /// Initializes a new `deserialize` instruction.
142    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        // Sanity check the number of operands.
149        check_number_of_operands(VARIANT, operands.len())?;
150        // Ensure that the operand type is valid.
151        check_operand_type_is_valid(VARIANT, &operand_type)?;
152        // Sanity check the destination type.
153        check_destination_type_is_valid(VARIANT, &destination_type)?;
154        // Return the instruction.
155        Ok(Self { operands, operand_type, destination, destination_type })
156    }
157
158    /// Returns the opcode.
159    pub const fn opcode() -> Opcode {
160        Opcode::Deserialize(DeserializeVariant::opcode(VARIANT))
161    }
162
163    /// Returns the operands in the operation.
164    pub fn operands(&self) -> &[Operand<N>] {
165        // Sanity check that the operands is the correct length.
166        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        // Return the operand.
172        &self.operands
173    }
174
175    /// Returns the operand type.
176    pub const fn operand_type(&self) -> &ArrayType<N> {
177        &self.operand_type
178    }
179
180    /// Returns the destination register.
181    #[inline]
182    pub fn destinations(&self) -> Vec<Register<N>> {
183        vec![self.destination.clone()]
184    }
185
186    /// Returns the destination register type.
187    #[inline]
188    pub const fn destination_type(&self) -> &PlaintextType<N> {
189        &self.destination_type
190    }
191
192    /// Returns whether this instruction refers to an external struct.
193    #[inline]
194    pub fn contains_external_struct(&self) -> bool {
195        self.destination_type.contains_external_struct()
196    }
197}
198
199/// Evaluate a `deserialize` operation.
200///
201/// This allows running `deserialize` without the machinery of stacks and registers.
202/// This is necessary for the Leo interpreter.
203pub 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    // Ensure that the depth is within the maximum limit.
230    if depth > N::MAX_DATA_DEPTH {
231        bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH)
232    }
233
234    // A helper to get the number of bits needed.
235    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    // Get the number of bits needed.
243    let size_in_bits = get_size_in_bits(destination_type)?;
244
245    // Check that the number of bits is correct.
246    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    // The starting index used to create subsequent subslices of the `bits` slice.
254    let mut index = 0;
255
256    // Helper function to get the next n bits as a slice.
257    let mut next_bits = |n: usize| -> Result<&[bool]> {
258        // Safely procure a subslice with the length `n` starting at `index`.
259        let subslice = bits.get(index..index + n);
260        // Check if the range is within bounds.
261        if let Some(next_bits) = subslice {
262            // Move the starting index.
263            index += n;
264            // Return the subslice.
265            Ok(next_bits)
266        } else {
267            bail!("Insufficient bits");
268        }
269    };
270
271    // Closure to deserialize a struct from a resolved `StructType<N>`.
272    let mut deserialize_struct = |struct_: &StructType<N>| -> Result<Plaintext<N>> {
273        // If the variant is `FromBits`, check the variant and metadata.
274        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        // Get the members.
287        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            // Get the expected size of the literal.
335            let expected_size = literal_type.size_in_bits::<N>();
336
337            // If the variant is `FromBits`, check the variant and metadata.
338            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            // Deserialize the literal.
359            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            // Get the struct.
364            let struct_ = get_struct(identifier)?;
365            deserialize_struct(&struct_)
366        }
367        PlaintextType::ExternalStruct(locator) => {
368            // Get the external struct.
369            let struct_ = get_external_struct(locator)?;
370            deserialize_struct(&struct_)
371        }
372        PlaintextType::Array(array_type) => {
373            // If the variant is `FromBits`, check the variant and metadata.
374            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            // Cache the plaintext bits, and return the array.
416            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    // Ensure that the depth is within the maximum limit.
436    if depth > A::Network::MAX_DATA_DEPTH {
437        bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH)
438    }
439
440    // A helper to get the number of bits needed.
441    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    // Get the number of bits needed.
449    let size_in_bits = get_size_in_bits(destination_type)?;
450
451    // Check that the number of bits is correct.
452    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    // The starting index used to create subsequent subslices of the `bits` slice.
460    let mut index = 0;
461
462    // Helper function to get the next n bits as a slice.
463    let mut next_bits = |n: usize| -> Result<&[circuit::Boolean<A>]> {
464        // Safely procure a subslice with the length `n` starting at `index`.
465        let subslice = bits.get(index..index + n);
466        // Check if the range is within bounds.
467        if let Some(next_bits) = subslice {
468            // Move the starting index.
469            index += n;
470            // Return the subslice.
471            Ok(next_bits)
472        } else {
473            bail!("Insufficient bits");
474        }
475    };
476
477    // Closure to deserialize a struct from a resolved `StructType<N>`.
478    let mut deserialize_struct = |struct_: &StructType<N>| -> Result<circuit::Plaintext<A>> {
479        // Get the expected number of members.
480        let expected_num_members =
481            u8::try_from(struct_.members().len()).map_err(|_| anyhow!("Struct exceeds maximum of entries."))?;
482
483        // If the variant is `FromBits`, check the variant and metadata.
484        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        // Get the members.
495        let mut members = IndexMap::with_capacity(struct_.members().len());
496
497        for (member_identifier, member_type) in struct_.members().iter() {
498            // Get the expected member size.
499            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 the variant is `FromBits`, check the member metadata.
503            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        // Cache the plaintext bits, and return the struct.
531        Ok(circuit::Plaintext::Struct(members, Default::default()))
532    };
533
534    match destination_type {
535        PlaintextType::Literal(literal_type) => {
536            // Get the expected size of the literal.
537            let expected_size = literal_type.size_in_bits::<A::Network>();
538
539            // If the variant is `FromBits`, check the variant and metadata.
540            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            // Deserialize the literal.
554            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            // Get the struct.
562            let struct_ = get_struct(identifier)?;
563            deserialize_struct(&struct_)
564        }
565        PlaintextType::ExternalStruct(_identifier) => {
566            // Get the external struct.
567            let struct_ = get_external_struct(_identifier)?;
568            deserialize_struct(&struct_)
569        }
570        PlaintextType::Array(array_type) => {
571            // Get the expected length of the array.
572            let expected_length = **array_type.length();
573
574            // If the variant is `FromBits`, check the variant and metadata.
575            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            // Cache the plaintext bits, and return the array.
609            Ok(circuit::Plaintext::Array(elements, Default::default()))
610        }
611    }
612}
613
614impl<N: Network, const VARIANT: u8> DeserializeInstruction<N, VARIANT> {
615    /// Evaluates the instruction.
616    pub fn evaluate(&self, stack: &impl StackTrait<N>, registers: &mut impl RegistersTrait<N>) -> Result<()> {
617        // Ensure the number of operands is correct.
618        check_number_of_operands(VARIANT, self.operands.len())?;
619        // Ensure that the operand type is valid.
620        check_operand_type_is_valid(VARIANT, &self.operand_type)?;
621        // Ensure the destination type is valid.
622        check_destination_type_is_valid(VARIANT, &self.destination_type)?;
623
624        // Load the operand.
625        let input = registers.load(stack, &self.operands[0])?;
626
627        // Get the bits of the operand.
628        let bits = match input {
629            Value::Plaintext(plaintext) => {
630                // Get the plaintext as a bit array.
631                plaintext.as_bit_array()?
632            }
633            _ => bail!("Expected input to be a plaintext bit array"),
634        };
635
636        // A helper to get a struct declaration.
637        let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
638
639        // A helper to get an external struct declaration.
640        let get_external_struct = |locator: &Locator<N>| {
641            stack.get_external_stack(locator.program_id())?.program().get_struct(locator.resource()).cloned()
642        };
643
644        // Get the size in bits of the operand.
645        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        // Check that the number of bits matches the desired length.
652        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        // Deserialize into the desired output.
659        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        // Store the output.
669        registers.store(stack, &self.destination, Value::Plaintext(output))
670    }
671
672    /// Executes the instruction.
673    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        // Ensure the number of operands is correct.
679        check_number_of_operands(VARIANT, self.operands.len())?;
680        // Ensure that the operand type is valid.
681        check_operand_type_is_valid(VARIANT, &self.operand_type)?;
682        // Ensure the destination type is valid.
683        check_destination_type_is_valid(VARIANT, &self.destination_type)?;
684
685        // Load the operand.
686        let input = registers.load_circuit(stack, &self.operands[0])?;
687
688        // Get the input as a bit array.
689        let bits = match input {
690            circuit::Value::Plaintext(plaintext) => plaintext.as_bit_array()?,
691            _ => bail!("Expected input to be a plaintext"),
692        };
693
694        // A helper to get a struct declaration.
695        let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
696
697        // A helper to get an external struct declaration.
698        let get_external_struct = |locator: &Locator<N>| {
699            stack.get_external_stack(locator.program_id())?.program().get_struct(locator.resource()).cloned()
700        };
701
702        // Get the size in bits of the operand.
703        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        // Check that the number of bits matches the desired length.
710        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        // Deserialize the bits into the desired literal type.
717        let output =
718            execute_deserialize_internal(VARIANT, &bits, &self.destination_type, &get_struct, &get_external_struct, 0)?;
719
720        // Store the output.
721        registers.store_circuit(stack, &self.destination, circuit::Value::Plaintext(output))
722    }
723
724    /// Finalizes the instruction.
725    #[inline]
726    pub fn finalize(&self, stack: &impl StackTrait<N>, registers: &mut impl RegistersTrait<N>) -> Result<()> {
727        self.evaluate(stack, registers)
728    }
729
730    /// Returns the output type from the given program and input types.
731    pub fn output_types(
732        &self,
733        stack: &impl StackTrait<N>,
734        input_types: &[RegisterType<N>],
735    ) -> Result<Vec<RegisterType<N>>> {
736        // Ensure the number of operands is correct.
737        check_number_of_operands(VARIANT, self.operands.len())?;
738        // Ensure the operand type is valid.
739        check_operand_type_is_valid(VARIANT, &self.operand_type)?;
740        // Ensure the destination type is valid.
741        check_destination_type_is_valid(VARIANT, &self.destination_type)?;
742
743        // Check that the input type matches the operand type.
744        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        // A helper to get a struct declaration.
751        let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
752
753        // A helper to get an external struct declaration.
754        let get_external_struct = |locator: &Locator<N>| {
755            stack.get_external_stack(locator.program_id())?.program().get_struct(locator.resource()).cloned()
756        };
757
758        // Get the size in bits of the operand.
759        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        // Check that the number of bits of the operand matches the destination.
766        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    /// Parses a string into an operation.
778    fn parse(string: &str) -> ParserResult<Self> {
779        /// Parse the operands from the string.
780        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                // Parse the whitespace from the string.
786                let (next_string, _) = Sanitizer::parse_whitespaces(string)?;
787                // Parse the operand from the string.
788                let (next_string, operand) = Operand::parse(next_string)?;
789                // Update the string.
790                string = next_string;
791                // Push the operand.
792                operands.push(operand);
793            }
794
795            Ok((string, operands))
796        }
797
798        // Parse the opcode from the string.
799        let (string, _) = tag(*Self::opcode())(string)?;
800        // Parse the operands from the string.
801        let (string, operands) = parse_operands(string, 1)?;
802
803        // Parse the whitespace from the string.
804        let (string, _) = Sanitizer::parse_whitespaces(string)?;
805        // Parse the "(" from the string.
806        let (string, _) = tag("(")(string)?;
807        // Parse the whitespace from the string.
808        let (string, _) = Sanitizer::parse_whitespaces(string)?;
809        // Parse the operand type from the string.
810        let (string, operand_type) = ArrayType::parse(string)?;
811        // Parse the ")" from the string.
812        let (string, _) = tag(")")(string)?;
813
814        // Parse the whitespace from the string.
815        let (string, _) = Sanitizer::parse_whitespaces(string)?;
816        // Parse the "into" from the string.
817        let (string, _) = tag("into")(string)?;
818        // Parse the whitespace from the string.
819        let (string, _) = Sanitizer::parse_whitespaces(string)?;
820        // Parse the destination register from the string.
821        let (string, destination) = Register::parse(string)?;
822
823        // Parse the whitespace from the string.
824        let (string, _) = Sanitizer::parse_whitespaces(string)?;
825        // Parse the "(" from the string.
826        let (string, _) = tag("(")(string)?;
827        // Parse the whitespace from the string.
828        let (string, _) = Sanitizer::parse_whitespaces(string)?;
829        // Parse the destination register type from the string.
830        let (string, destination_type) = PlaintextType::parse(string)?;
831        // Parse the ")" from the string.
832        let (string, _) = tag(")")(string)?;
833
834        // Construct the instruction, checking for errors.
835        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    /// Parses a string into an operation.
848    fn from_str(string: &str) -> Result<Self> {
849        match Self::parse(string) {
850            Ok((remainder, object)) => {
851                // Ensure the remainder is empty.
852                ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
853                // Return the object.
854                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    /// Prints the operation as a string.
863    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    /// Prints the operation to a string.
870    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    /// Reads the operation from a buffer.
879    fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
880        // Read the operand.
881        let operand = Operand::read_le(&mut reader)?;
882        // Read the operand type.
883        let operand_type = ArrayType::read_le(&mut reader)?;
884        // Read the destination register.
885        let destination = Register::read_le(&mut reader)?;
886        // Read the destination register type.
887        let destination_type = PlaintextType::read_le(&mut reader)?;
888        // Return the operation.
889        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    /// Writes the operation to a buffer.
898    fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
899        // Write the operands.
900        self.operands.iter().try_for_each(|operand| operand.write_le(&mut writer))?;
901        // Write the operand type.
902        self.operand_type.write_le(&mut writer)?;
903        // Write the destination register.
904        self.destination.write_le(&mut writer)?;
905        // Write the destination register type.
906        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    /// **Attention**: When changing this, also update in `tests/instruction/deserialize.rs`.
918    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    /// Randomly sample a source type.
939    fn sample_source_type<N: Network, const VARIANT: u8>(rng: &mut TestRng) -> ArrayType<N> {
940        // Generate a random array length between 1 and N::LATEST_MAX_ARRAY_ELEMENTS().
941        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        // Initialize an RNG.
977        let rng = &mut TestRng::default();
978
979        // Run the parser test for each variant.
980        run_parser_test::<{ DeserializeVariant::FromBits as u8 }>(rng);
981        run_parser_test::<{ DeserializeVariant::FromBitsRaw as u8 }>(rng);
982    }
983}