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        Plaintext,
25        PlaintextType,
26        Register,
27        RegisterType,
28        StructType,
29        U8,
30        U16,
31        U32,
32        Value,
33    },
34};
35
36use indexmap::IndexMap;
37
38/// Deserializes the bits into a value.
39pub type DeserializeBits<N> = DeserializeInstruction<N, { DeserializeVariant::FromBits as u8 }>;
40/// Deserializes the raw bits into a value.
41pub type DeserializeBitsRaw<N> = DeserializeInstruction<N, { DeserializeVariant::FromBitsRaw as u8 }>;
42
43/// The deserialization variant.
44#[derive(Debug, Clone, Eq, PartialEq)]
45pub enum DeserializeVariant {
46    FromBits,
47    FromBitsRaw,
48}
49
50impl DeserializeVariant {
51    // Returns the opcode associated with the variant.
52    pub const fn opcode(variant: u8) -> &'static str {
53        match variant {
54            0 => "deserialize.bits",
55            1 => "deserialize.bits.raw",
56            _ => panic!("Invalid 'deserialize' instruction opcode"),
57        }
58    }
59
60    // Returns the variant, given a `u8`.
61    pub const fn from_u8(variant: u8) -> Self {
62        match variant {
63            0 => Self::FromBits,
64            1 => Self::FromBitsRaw,
65            _ => panic!("Invalid 'deserialize' instruction variant"),
66        }
67    }
68}
69
70/// Checks that the number of operands is correct.
71fn check_number_of_operands(variant: u8, num_operands: usize) -> Result<()> {
72    if num_operands != 1 {
73        bail!("Instruction '{}' expects 1 operand, found {num_operands} operands", DeserializeVariant::opcode(variant))
74    }
75    Ok(())
76}
77
78/// Checks that the operand type is valid.
79fn check_operand_type_is_valid(variant: u8, array_type: &ArrayType<impl Network>) -> Result<()> {
80    match variant {
81        0 | 1 if array_type.is_bit_array() => Ok(()),
82        _ => {
83            bail!("Instruction '{}' cannot output type '{array_type}'", DeserializeVariant::opcode(variant))
84        }
85    }
86}
87
88/// Check that the destination type is valid.
89fn check_destination_type_is_valid(variant: u8, destination_type: &PlaintextType<impl Network>) -> Result<()> {
90    // A helper function to check a literal type.
91    fn check_literal_type(literal_type: &LiteralType) -> Result<()> {
92        match literal_type {
93            LiteralType::Address
94            | LiteralType::Boolean
95            | LiteralType::Field
96            | LiteralType::Group
97            | LiteralType::I8
98            | LiteralType::I16
99            | LiteralType::I32
100            | LiteralType::I64
101            | LiteralType::I128
102            | LiteralType::U8
103            | LiteralType::U16
104            | LiteralType::U32
105            | LiteralType::U64
106            | LiteralType::U128
107            | LiteralType::Scalar => Ok(()),
108            _ => bail!("Invalid literal type '{literal_type}' for 'deserialize' instruction"),
109        }
110    }
111
112    match destination_type {
113        PlaintextType::Literal(literal_type) => check_literal_type(literal_type),
114        PlaintextType::Array(array_type) => match array_type.base_element_type() {
115            PlaintextType::Literal(literal_type) => check_literal_type(literal_type),
116            _ => bail!("Invalid element type '{array_type}' for 'deserialize' instruction"),
117        },
118        _ => bail!(
119            "Instruction '{}' cannot take type '{destination_type}' as input",
120            DeserializeVariant::opcode(variant)
121        ),
122    }
123}
124
125/// Deserializes the operand into the declared type.
126#[derive(Clone, PartialEq, Eq, Hash)]
127pub struct DeserializeInstruction<N: Network, const VARIANT: u8> {
128    /// The operand as `input`.
129    operands: Vec<Operand<N>>,
130    /// The operand type.
131    operand_type: ArrayType<N>,
132    /// The destination register.
133    destination: Register<N>,
134    /// The destination register type.
135    destination_type: PlaintextType<N>,
136}
137
138impl<N: Network, const VARIANT: u8> DeserializeInstruction<N, VARIANT> {
139    /// Initializes a new `deserialize` instruction.
140    pub fn new(
141        operands: Vec<Operand<N>>,
142        operand_type: ArrayType<N>,
143        destination: Register<N>,
144        destination_type: PlaintextType<N>,
145    ) -> Result<Self> {
146        // Sanity check the number of operands.
147        check_number_of_operands(VARIANT, operands.len())?;
148        // Ensure that the operand type is valid.
149        check_operand_type_is_valid(VARIANT, &operand_type)?;
150        // Sanity check the destination type.
151        check_destination_type_is_valid(VARIANT, &destination_type)?;
152        // Return the instruction.
153        Ok(Self { operands, operand_type, destination, destination_type })
154    }
155
156    /// Returns the opcode.
157    pub const fn opcode() -> Opcode {
158        Opcode::Deserialize(DeserializeVariant::opcode(VARIANT))
159    }
160
161    /// Returns the operands in the operation.
162    pub fn operands(&self) -> &[Operand<N>] {
163        // Sanity check that the operands is the correct length.
164        if cfg!(debug_assertions) {
165            check_number_of_operands(VARIANT, self.operands.len()).unwrap();
166            check_operand_type_is_valid(VARIANT, &self.operand_type).unwrap();
167            check_destination_type_is_valid(VARIANT, &self.destination_type).unwrap();
168        }
169        // Return the operand.
170        &self.operands
171    }
172
173    /// Returns the operand type.
174    pub const fn operand_type(&self) -> &ArrayType<N> {
175        &self.operand_type
176    }
177
178    /// Returns the destination register.
179    #[inline]
180    pub fn destinations(&self) -> Vec<Register<N>> {
181        vec![self.destination.clone()]
182    }
183
184    /// Returns the destination register type.
185    #[inline]
186    pub const fn destination_type(&self) -> &PlaintextType<N> {
187        &self.destination_type
188    }
189}
190
191/// Evaluate a `deserialize` operation.
192///
193/// This allows running `deserialize` without the machinery of stacks and registers.
194/// This is necessary for the Leo interpreter.
195pub fn evaluate_deserialize<N: Network, F>(
196    variant: DeserializeVariant,
197    bits: &[bool],
198    destination_type: &PlaintextType<N>,
199    get_struct: &F,
200) -> Result<Plaintext<N>>
201where
202    F: Fn(&Identifier<N>) -> Result<StructType<N>>,
203{
204    evaluate_deserialize_internal(variant as u8, bits, destination_type, get_struct, 0)
205}
206
207fn evaluate_deserialize_internal<N: Network, F>(
208    variant: u8,
209    bits: &[bool],
210    destination_type: &PlaintextType<N>,
211    get_struct: &F,
212    depth: usize,
213) -> Result<Plaintext<N>>
214where
215    F: Fn(&Identifier<N>) -> Result<StructType<N>>,
216{
217    // Ensure that the depth is within the maximum limit.
218    if depth > N::MAX_DATA_DEPTH {
219        bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH)
220    }
221
222    // A helper to get the number of bits needed.
223    let get_size_in_bits = |plaintext_type: &PlaintextType<N>| -> Result<usize> {
224        match DeserializeVariant::from_u8(variant) {
225            DeserializeVariant::FromBits => plaintext_type.size_in_bits(&get_struct),
226            DeserializeVariant::FromBitsRaw => plaintext_type.size_in_bits_raw(&get_struct),
227        }
228    };
229
230    // Get the number of bits needed.
231    let size_in_bits = get_size_in_bits(destination_type)?;
232
233    // Check that the number of bits is correct.
234    let bits = bits.to_vec();
235    ensure!(
236        bits.len() == size_in_bits,
237        "The number of bits of the operand '{}' does not match the destination '{size_in_bits}'",
238        bits.len()
239    );
240
241    // The starting index used to create subsequent subslices of the `bits` slice.
242    let mut index = 0;
243
244    // Helper function to get the next n bits as a slice.
245    let mut next_bits = |n: usize| -> Result<&[bool]> {
246        // Safely procure a subslice with the length `n` starting at `index`.
247        let subslice = bits.get(index..index + n);
248        // Check if the range is within bounds.
249        if let Some(next_bits) = subslice {
250            // Move the starting index.
251            index += n;
252            // Return the subslice.
253            Ok(next_bits)
254        } else {
255            bail!("Insufficient bits");
256        }
257    };
258
259    match destination_type {
260        PlaintextType::Literal(literal_type) => {
261            // Get the expected size of the literal.
262            let expected_size = literal_type.size_in_bits::<N>();
263
264            // If the variant is `FromBits`, check the variant and metadata.
265            if variant == (DeserializeVariant::FromBits as u8) {
266                let plaintext_variant = next_bits(2)?;
267                let plaintext_variant = [plaintext_variant[0], plaintext_variant[1]];
268                ensure!(
269                    plaintext_variant == PlaintextType::<N>::LITERAL_PREFIX_BITS,
270                    "Invalid plaintext variant for literal type '{literal_type}'"
271                );
272
273                let literal_variant = u8::from_bits_le(next_bits(8)?)?;
274                ensure!(
275                    literal_variant == literal_type.type_id(),
276                    "Mismatched literal type. Expected '{literal_type}', found '{literal_variant}'"
277                );
278
279                let literal_size = u16::from_bits_le(next_bits(16)?)?;
280                ensure!(
281                    literal_size == expected_size,
282                    "Mismatched literal size. Expected '{expected_size}', found '{literal_size}'",
283                );
284            };
285            // Deserialize the literal.
286            let literal = Literal::from_bits_le(literal_type.type_id(), next_bits(expected_size as usize)?)?;
287            Ok(Plaintext::Literal(literal, Default::default()))
288        }
289        PlaintextType::Struct(identifier) => {
290            // Get the struct.
291            let struct_ = get_struct(identifier)?;
292            // If the variant is `FromBits`, check the variant and metadata.
293            if variant == (DeserializeVariant::FromBits as u8) {
294                let plaintext_variant = next_bits(2)?;
295                let plaintext_variant = [plaintext_variant[0], plaintext_variant[1]];
296                ensure!(
297                    plaintext_variant == PlaintextType::<N>::STRUCT_PREFIX_BITS,
298                    "Invalid plaintext variant for struct type '{identifier}'"
299                );
300
301                let num_members = u8::from_bits_le(next_bits(8)?)?;
302                ensure!(struct_.members().len() == num_members as usize, "Struct exceeds maximum of entries.");
303            }
304
305            // Get the members.
306            let mut members = IndexMap::with_capacity(struct_.members().len());
307
308            for (member_identifier, member_type) in struct_.members().iter() {
309                // Get the expected member size.
310                let expected_member_size = get_size_in_bits(member_type)?;
311
312                // If the variant is `FromBits`, check the member metadata.
313                if variant == (DeserializeVariant::FromBits as u8) {
314                    let identifier_size = u8::from_bits_le(next_bits(8)?)?;
315                    ensure!(
316                        member_identifier.size_in_bits() == identifier_size,
317                        "Mismatched identifier size. Expected '{}', found '{}'",
318                        member_identifier.size_in_bits(),
319                        identifier_size
320                    );
321
322                    let identifier_bits = next_bits(identifier_size as usize)?;
323                    let identifier = Identifier::<N>::from_bits_le(identifier_bits)?;
324                    ensure!(
325                        *member_identifier == identifier,
326                        "Mismatched identifier. Expected '{member_identifier}', found '{identifier}'",
327                    );
328
329                    let member_size = u16::from_bits_le(next_bits(16)?)?;
330                    ensure!(
331                        member_size as usize == expected_member_size,
332                        "Mismatched member size. Expected '{expected_member_size}', found '{member_size}'",
333                    );
334                }
335
336                let value = evaluate_deserialize_internal(
337                    variant,
338                    next_bits(expected_member_size)?,
339                    member_type,
340                    get_struct,
341                    depth + 1,
342                )?;
343
344                if members.insert(*member_identifier, value).is_some() {
345                    bail!("Duplicate identifier in struct.");
346                }
347            }
348
349            // Cache the plaintext bits, and return the struct.
350            Ok(Plaintext::Struct(members, Default::default()))
351        }
352        PlaintextType::Array(array_type) => {
353            // If the variant is `FromBits`, check the variant and metadata.
354            if variant == (DeserializeVariant::FromBits as u8) {
355                let plaintext_variant = next_bits(2)?;
356                let plaintext_variant = [plaintext_variant[0], plaintext_variant[1]];
357                ensure!(
358                    plaintext_variant == PlaintextType::<N>::ARRAY_PREFIX_BITS,
359                    "Invalid plaintext variant for array type"
360                );
361
362                let num_elements = u32::from_bits_le(next_bits(32)?)?;
363                ensure!(
364                    **array_type.length() == num_elements,
365                    "Mismatched array length. Expected '{}', found '{}'",
366                    **array_type.length(),
367                    num_elements
368                );
369            }
370
371            let expected_element_type = array_type.next_element_type();
372            let expected_element_size = get_size_in_bits(expected_element_type)?;
373
374            let mut elements = Vec::with_capacity(**array_type.length() as usize);
375
376            for _ in 0..**array_type.length() {
377                if variant == (DeserializeVariant::FromBits as u8) {
378                    let element_size = u16::from_bits_le(next_bits(16)?)?;
379                    ensure!(
380                        element_size as usize == expected_element_size,
381                        "Mismatched element size. Expected '{expected_element_size}', found '{element_size}'",
382                    );
383                }
384                let element = evaluate_deserialize_internal(
385                    variant,
386                    next_bits(expected_element_size)?,
387                    expected_element_type,
388                    get_struct,
389                    depth + 1,
390                )?;
391                elements.push(element);
392            }
393
394            // Cache the plaintext bits, and return the array.
395            Ok(Plaintext::Array(elements, Default::default()))
396        }
397    }
398}
399
400fn execute_deserialize_internal<A: circuit::Aleo<Network = N>, N: Network, F>(
401    variant: u8,
402    bits: &[circuit::Boolean<A>],
403    destination_type: &PlaintextType<N>,
404    get_struct: &F,
405    depth: usize,
406) -> Result<circuit::Plaintext<A>>
407where
408    F: Fn(&Identifier<N>) -> Result<StructType<N>>,
409{
410    use snarkvm_circuit::{Inject, traits::FromBits};
411
412    // Ensure that the depth is within the maximum limit.
413    if depth > A::Network::MAX_DATA_DEPTH {
414        bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH)
415    }
416
417    // A helper to get the number of bits needed.
418    let get_size_in_bits = |plaintext_type: &PlaintextType<N>| -> Result<usize> {
419        match DeserializeVariant::from_u8(variant) {
420            DeserializeVariant::FromBits => plaintext_type.size_in_bits(get_struct),
421            DeserializeVariant::FromBitsRaw => plaintext_type.size_in_bits_raw(get_struct),
422        }
423    };
424
425    // Get the number of bits needed.
426    let size_in_bits = get_size_in_bits(destination_type)?;
427
428    // Check that the number of bits is correct.
429    let bits = bits.to_vec();
430    ensure!(
431        bits.len() == size_in_bits,
432        "The number of bits of the operand '{}' does not match the destination '{size_in_bits}'",
433        bits.len()
434    );
435
436    // The starting index used to create subsequent subslices of the `bits` slice.
437    let mut index = 0;
438
439    // Helper function to get the next n bits as a slice.
440    let mut next_bits = |n: usize| -> Result<&[circuit::Boolean<A>]> {
441        // Safely procure a subslice with the length `n` starting at `index`.
442        let subslice = bits.get(index..index + n);
443        // Check if the range is within bounds.
444        if let Some(next_bits) = subslice {
445            // Move the starting index.
446            index += n;
447            // Return the subslice.
448            Ok(next_bits)
449        } else {
450            bail!("Insufficient bits");
451        }
452    };
453
454    match destination_type {
455        PlaintextType::Literal(literal_type) => {
456            // Get the expected size of the literal.
457            let expected_size = literal_type.size_in_bits::<A::Network>();
458
459            // If the variant is `FromBits`, check the variant and metadata.
460            if variant == (DeserializeVariant::FromBits as u8) {
461                let plaintext_variant = next_bits(2)?;
462                let expected_bits =
463                    PlaintextType::<A::Network>::LITERAL_PREFIX_BITS.map(circuit::Boolean::<A>::constant);
464                A::assert_eq(&expected_bits[0], &plaintext_variant[0]);
465                A::assert_eq(&expected_bits[1], &plaintext_variant[1]);
466
467                let literal_variant = circuit::U8::<A>::from_bits_le(next_bits(8)?);
468                A::assert_eq(&literal_variant, circuit::U8::<A>::constant(U8::new(literal_type.type_id())));
469
470                let literal_size = circuit::U16::<A>::from_bits_le(next_bits(16)?);
471                A::assert_eq(&literal_size, circuit::U16::<A>::constant(U16::new(expected_size)));
472            };
473            // Deserialize the literal.
474            let literal = circuit::Literal::<A>::from_bits_le(
475                &circuit::U8::<A>::constant(U8::new(literal_type.type_id())),
476                next_bits(expected_size as usize)?,
477            );
478            Ok(circuit::Plaintext::from(literal))
479        }
480        PlaintextType::Struct(identifier) => {
481            // Get the struct.
482            let struct_ = get_struct(identifier)?;
483
484            // Get the expected number of members.
485            let expected_num_members =
486                u8::try_from(struct_.members().len()).map_err(|_| anyhow!("Struct exceeds maximum of entries."))?;
487
488            // If the variant is `FromBits`, check the variant and metadata.
489            if variant == (DeserializeVariant::FromBits as u8) {
490                let plaintext_variant = next_bits(2)?;
491                let expected_bits =
492                    PlaintextType::<A::Network>::STRUCT_PREFIX_BITS.map(circuit::Boolean::<A>::constant);
493                A::assert_eq(&expected_bits[0], &plaintext_variant[0]);
494                A::assert_eq(&expected_bits[1], &plaintext_variant[1]);
495
496                let num_members = circuit::U8::<A>::from_bits_le(next_bits(8)?);
497                A::assert_eq(num_members, circuit::U8::<A>::constant(U8::new(expected_num_members)));
498            }
499
500            // Get the members.
501            let mut members = IndexMap::with_capacity(struct_.members().len());
502
503            for (member_identifier, member_type) in struct_.members().iter() {
504                // Get the expected member size.
505                let expected_member_size = u16::try_from(get_size_in_bits(member_type)?)
506                    .map_err(|_| anyhow!("Member size exceeds maximum of 65535 bits."))?;
507
508                // If the variant is `FromBits`, check the member metadata.
509                if variant == (DeserializeVariant::FromBits as u8) {
510                    let expected_identifier_size = member_identifier.size_in_bits();
511                    let identifier_size = circuit::U8::<A>::from_bits_le(next_bits(8)?);
512                    A::assert_eq(&identifier_size, circuit::U8::<A>::constant(U8::new(expected_identifier_size)));
513
514                    let identifier_bits = next_bits(expected_identifier_size as usize)?;
515                    let identifier = circuit::Identifier::<A>::from_bits_le(identifier_bits);
516                    A::assert_eq(circuit::Identifier::<A>::constant(*member_identifier), &identifier);
517
518                    let member_size = circuit::U16::<A>::from_bits_le(next_bits(16)?);
519                    A::assert_eq(&member_size, circuit::U16::<A>::constant(U16::new(expected_member_size)));
520                }
521
522                let value = execute_deserialize_internal(
523                    variant,
524                    next_bits(expected_member_size as usize)?,
525                    member_type,
526                    get_struct,
527                    depth + 1,
528                )?;
529
530                if members.insert(circuit::Identifier::constant(*member_identifier), value).is_some() {
531                    bail!("Duplicate identifier in struct.");
532                }
533            }
534
535            // Cache the plaintext bits, and return the struct.
536            Ok(circuit::Plaintext::Struct(members, Default::default()))
537        }
538        PlaintextType::Array(array_type) => {
539            // Get the expected length of the array.
540            let expected_length = **array_type.length();
541
542            // If the variant is `FromBits`, check the variant and metadata.
543            if variant == (DeserializeVariant::FromBits as u8) {
544                let plaintext_variant = next_bits(2)?;
545                let expected_bits = PlaintextType::<A::Network>::ARRAY_PREFIX_BITS.map(circuit::Boolean::<A>::constant);
546                A::assert_eq(&expected_bits[0], &plaintext_variant[0]);
547                A::assert_eq(&expected_bits[1], &plaintext_variant[1]);
548
549                let num_elements = circuit::U32::<A>::from_bits_le(next_bits(32)?);
550                A::assert_eq(&num_elements, circuit::U32::<A>::constant(U32::new(expected_length)));
551            }
552
553            let expected_element_type = array_type.next_element_type();
554            let expected_element_size = u16::try_from(get_size_in_bits(expected_element_type)?)
555                .map_err(|_| anyhow!("Element size exceeds maximum of 65535 bits."))?;
556
557            let mut elements = Vec::with_capacity(expected_length as usize);
558
559            for _ in 0..**array_type.length() {
560                if variant == (DeserializeVariant::FromBits as u8) {
561                    let element_size = circuit::U16::<A>::from_bits_le(next_bits(16)?);
562                    A::assert_eq(&element_size, circuit::U16::<A>::constant(U16::new(expected_element_size)));
563                }
564
565                let element = execute_deserialize_internal(
566                    variant,
567                    next_bits(expected_element_size as usize)?,
568                    expected_element_type,
569                    get_struct,
570                    depth + 1,
571                )?;
572                elements.push(element);
573            }
574
575            // Cache the plaintext bits, and return the array.
576            Ok(circuit::Plaintext::Array(elements, Default::default()))
577        }
578    }
579}
580
581impl<N: Network, const VARIANT: u8> DeserializeInstruction<N, VARIANT> {
582    /// Evaluates the instruction.
583    pub fn evaluate(&self, stack: &impl StackTrait<N>, registers: &mut impl RegistersTrait<N>) -> Result<()> {
584        // Ensure the number of operands is correct.
585        check_number_of_operands(VARIANT, self.operands.len())?;
586        // Ensure that the operand type is valid.
587        check_operand_type_is_valid(VARIANT, &self.operand_type)?;
588        // Ensure the destination type is valid.
589        check_destination_type_is_valid(VARIANT, &self.destination_type)?;
590
591        // Load the operand.
592        let input = registers.load(stack, &self.operands[0])?;
593
594        // Get the bits of the operand.
595        let bits = match input {
596            Value::Plaintext(plaintext) => {
597                // Get the plaintext as a bit array.
598                plaintext.as_bit_array()?
599            }
600            _ => bail!("Expected input to be a plaintext bit array"),
601        };
602
603        // A helper to get a struct declaration.
604        let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
605
606        // Get the size in bits of the operand.
607        let size_in_bits = match VARIANT {
608            0 => self.destination_type.size_in_bits(&get_struct)?,
609            1 => self.destination_type.size_in_bits_raw(&get_struct)?,
610            variant => bail!("Invalid `deserialize` variant '{variant}'"),
611        };
612
613        // Check that the number of bits matches the desired length.
614        ensure!(
615            bits.len() == size_in_bits as usize,
616            "The number of bits of the operand '{}' does not match the destination '{size_in_bits}'",
617            bits.len()
618        );
619
620        // Deserialize into the desired output.
621        let output = evaluate_deserialize_internal(VARIANT, &bits, &self.destination_type, &get_struct, 0)?;
622
623        // Store the output.
624        registers.store(stack, &self.destination, Value::Plaintext(output))
625    }
626
627    /// Executes the instruction.
628    pub fn execute<A: circuit::Aleo<Network = N>>(
629        &self,
630        stack: &impl StackTrait<N>,
631        registers: &mut impl RegistersCircuit<N, A>,
632    ) -> Result<()> {
633        // Ensure the number of operands is correct.
634        check_number_of_operands(VARIANT, self.operands.len())?;
635        // Ensure that the operand type is valid.
636        check_operand_type_is_valid(VARIANT, &self.operand_type)?;
637        // Ensure the destination type is valid.
638        check_destination_type_is_valid(VARIANT, &self.destination_type)?;
639
640        // Load the operand.
641        let input = registers.load_circuit(stack, &self.operands[0])?;
642
643        // Get the input as a bit array.
644        let bits = match input {
645            circuit::Value::Plaintext(plaintext) => plaintext.as_bit_array()?,
646            _ => bail!("Expected input to be a plaintext"),
647        };
648
649        // A helper to get a struct declaration.
650        let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
651
652        // Get the size in bits of the operand.
653        let size_in_bits = match VARIANT {
654            0 => self.destination_type.size_in_bits(&get_struct)?,
655            1 => self.destination_type.size_in_bits_raw(&get_struct)?,
656            variant => bail!("Invalid `deserialize` variant '{variant}'"),
657        };
658
659        // Check that the number of bits matches the desired length.
660        ensure!(
661            bits.len() == size_in_bits as usize,
662            "The number of bits of the operand '{}' does not match the destination '{size_in_bits}'",
663            bits.len()
664        );
665
666        // Deserialize the bits into the desired literal type.
667        let output = execute_deserialize_internal(VARIANT, &bits, &self.destination_type, &get_struct, 0)?;
668
669        // Store the output.
670        registers.store_circuit(stack, &self.destination, circuit::Value::Plaintext(output))
671    }
672
673    /// Finalizes the instruction.
674    #[inline]
675    pub fn finalize(&self, stack: &impl StackTrait<N>, registers: &mut impl RegistersTrait<N>) -> Result<()> {
676        self.evaluate(stack, registers)
677    }
678
679    /// Returns the output type from the given program and input types.
680    pub fn output_types(
681        &self,
682        stack: &impl StackTrait<N>,
683        input_types: &[RegisterType<N>],
684    ) -> Result<Vec<RegisterType<N>>> {
685        // Ensure the number of operands is correct.
686        check_number_of_operands(VARIANT, self.operands.len())?;
687        // Ensure the operand type is valid.
688        check_operand_type_is_valid(VARIANT, &self.operand_type)?;
689        // Ensure the destination type is valid.
690        check_destination_type_is_valid(VARIANT, &self.destination_type)?;
691
692        // Check that the input type matches the operand type.
693        ensure!(input_types.len() == 1, "Expected exactly one input type");
694        match &input_types[0] {
695            RegisterType::Plaintext(PlaintextType::Array(array_type)) if array_type == &self.operand_type => {}
696            _ => bail!("Input type {:?} does not match operand type {:?}", input_types[0], self.operand_type),
697        }
698
699        // A helper to get a struct declaration.
700        let get_struct = |identifier: &Identifier<N>| stack.program().get_struct(identifier).cloned();
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)?,
705            1 => self.destination_type.size_in_bits_raw(&get_struct)?,
706            variant => bail!("Invalid `deserialize` variant '{variant}'"),
707        };
708
709        // Check that the number of bits of the operand matches the destination.
710        ensure!(
711            **self.operand_type.length() as usize == size_in_bits,
712            "The number of bits of the operand '{}' does not match the destination '{size_in_bits}'",
713            **self.operand_type.length()
714        );
715
716        Ok(vec![RegisterType::Plaintext(self.destination_type.clone())])
717    }
718}
719
720impl<N: Network, const VARIANT: u8> Parser for DeserializeInstruction<N, VARIANT> {
721    /// Parses a string into an operation.
722    fn parse(string: &str) -> ParserResult<Self> {
723        /// Parse the operands from the string.
724        fn parse_operands<N: Network>(string: &str, num_operands: usize) -> ParserResult<Vec<Operand<N>>> {
725            let mut operands = Vec::with_capacity(num_operands);
726            let mut string = string;
727
728            for _ in 0..num_operands {
729                // Parse the whitespace from the string.
730                let (next_string, _) = Sanitizer::parse_whitespaces(string)?;
731                // Parse the operand from the string.
732                let (next_string, operand) = Operand::parse(next_string)?;
733                // Update the string.
734                string = next_string;
735                // Push the operand.
736                operands.push(operand);
737            }
738
739            Ok((string, operands))
740        }
741
742        // Parse the opcode from the string.
743        let (string, _) = tag(*Self::opcode())(string)?;
744        // Parse the operands from the string.
745        let (string, operands) = parse_operands(string, 1)?;
746
747        // Parse the whitespace from the string.
748        let (string, _) = Sanitizer::parse_whitespaces(string)?;
749        // Parse the "(" from the string.
750        let (string, _) = tag("(")(string)?;
751        // Parse the whitespace from the string.
752        let (string, _) = Sanitizer::parse_whitespaces(string)?;
753        // Parse the operand type from the string.
754        let (string, operand_type) = ArrayType::parse(string)?;
755        // Parse the ")" from the string.
756        let (string, _) = tag(")")(string)?;
757
758        // Parse the whitespace from the string.
759        let (string, _) = Sanitizer::parse_whitespaces(string)?;
760        // Parse the "into" from the string.
761        let (string, _) = tag("into")(string)?;
762        // Parse the whitespace from the string.
763        let (string, _) = Sanitizer::parse_whitespaces(string)?;
764        // Parse the destination register from the string.
765        let (string, destination) = Register::parse(string)?;
766
767        // Parse the whitespace from the string.
768        let (string, _) = Sanitizer::parse_whitespaces(string)?;
769        // Parse the "(" from the string.
770        let (string, _) = tag("(")(string)?;
771        // Parse the whitespace from the string.
772        let (string, _) = Sanitizer::parse_whitespaces(string)?;
773        // Parse the destination register type from the string.
774        let (string, destination_type) = PlaintextType::parse(string)?;
775        // Parse the ")" from the string.
776        let (string, _) = tag(")")(string)?;
777
778        // Construct the instruction, checking for errors.
779        match Self::new(operands, operand_type, destination, destination_type) {
780            Ok(instruction) => Ok((string, instruction)),
781            Err(e) => map_res(fail, |_: ParserResult<Self>| {
782                Err(error(format!("Failed to parse '{}' instruction: {e}", Self::opcode())))
783            })(string),
784        }
785    }
786}
787
788impl<N: Network, const VARIANT: u8> FromStr for DeserializeInstruction<N, VARIANT> {
789    type Err = Error;
790
791    /// Parses a string into an operation.
792    fn from_str(string: &str) -> Result<Self> {
793        match Self::parse(string) {
794            Ok((remainder, object)) => {
795                // Ensure the remainder is empty.
796                ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
797                // Return the object.
798                Ok(object)
799            }
800            Err(error) => bail!("Failed to parse string. {error}"),
801        }
802    }
803}
804
805impl<N: Network, const VARIANT: u8> Debug for DeserializeInstruction<N, VARIANT> {
806    /// Prints the operation as a string.
807    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
808        Display::fmt(self, f)
809    }
810}
811
812impl<N: Network, const VARIANT: u8> Display for DeserializeInstruction<N, VARIANT> {
813    /// Prints the operation to a string.
814    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
815        write!(f, "{} ", Self::opcode())?;
816        self.operands.iter().try_for_each(|operand| write!(f, "{operand} "))?;
817        write!(f, " ({}) into {} ({})", self.operand_type, self.destination, self.destination_type)
818    }
819}
820
821impl<N: Network, const VARIANT: u8> FromBytes for DeserializeInstruction<N, VARIANT> {
822    /// Reads the operation from a buffer.
823    fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
824        // Read the operand.
825        let operand = Operand::read_le(&mut reader)?;
826        // Read the operand type.
827        let operand_type = ArrayType::read_le(&mut reader)?;
828        // Read the destination register.
829        let destination = Register::read_le(&mut reader)?;
830        // Read the destination register type.
831        let destination_type = PlaintextType::read_le(&mut reader)?;
832        // Return the operation.
833        match Self::new(vec![operand], operand_type, destination, destination_type) {
834            Ok(instruction) => Ok(instruction),
835            Err(e) => Err(error(format!("Failed to read '{}' instruction: {e}", Self::opcode()))),
836        }
837    }
838}
839
840impl<N: Network, const VARIANT: u8> ToBytes for DeserializeInstruction<N, VARIANT> {
841    /// Writes the operation to a buffer.
842    fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
843        // Write the operands.
844        self.operands.iter().try_for_each(|operand| operand.write_le(&mut writer))?;
845        // Write the operand type.
846        self.operand_type.write_le(&mut writer)?;
847        // Write the destination register.
848        self.destination.write_le(&mut writer)?;
849        // Write the destination register type.
850        self.destination_type.write_le(&mut writer)
851    }
852}
853
854#[cfg(test)]
855mod tests {
856    use super::*;
857    use console::{network::MainnetV0, types::U32};
858
859    type CurrentNetwork = MainnetV0;
860
861    /// **Attention**: When changing this, also update in `tests/instruction/deserialize.rs`.
862    fn valid_destination_types<N: Network>() -> &'static [PlaintextType<N>] {
863        &[
864            PlaintextType::Literal(LiteralType::Address),
865            PlaintextType::Literal(LiteralType::Field),
866            PlaintextType::Literal(LiteralType::Group),
867            PlaintextType::Literal(LiteralType::I8),
868            PlaintextType::Literal(LiteralType::I16),
869            PlaintextType::Literal(LiteralType::I32),
870            PlaintextType::Literal(LiteralType::I64),
871            PlaintextType::Literal(LiteralType::I128),
872            PlaintextType::Literal(LiteralType::U8),
873            PlaintextType::Literal(LiteralType::U16),
874            PlaintextType::Literal(LiteralType::U32),
875            PlaintextType::Literal(LiteralType::U64),
876            PlaintextType::Literal(LiteralType::U128),
877            PlaintextType::Literal(LiteralType::Scalar),
878        ]
879    }
880
881    /// Randomly sample a source type.
882    fn sample_source_type<N: Network, const VARIANT: u8>(rng: &mut TestRng) -> ArrayType<N> {
883        // Generate a random array length between 1 and N::MAX_ARRAY_ELEMENTS.
884        let array_length = 1 + (u32::rand(rng) % u32::try_from(N::MAX_ARRAY_ELEMENTS).unwrap());
885        match VARIANT {
886            0 | 1 => {
887                ArrayType::new(PlaintextType::Literal(LiteralType::Boolean), vec![U32::new(array_length)]).unwrap()
888            }
889            _ => panic!("Invalid variant"),
890        }
891    }
892
893    fn run_parser_test<const VARIANT: u8>(rng: &mut TestRng) {
894        for destination_type in valid_destination_types::<CurrentNetwork>() {
895            {
896                let opcode = DeserializeVariant::opcode(VARIANT);
897                let source_type = sample_source_type::<CurrentNetwork, VARIANT>(rng);
898                let instruction = format!("{opcode} r0 ({source_type}) into r1 ({destination_type})",);
899                println!("Parsing instruction: '{instruction}'");
900
901                let (string, deserialize) =
902                    DeserializeInstruction::<CurrentNetwork, VARIANT>::parse(&instruction).unwrap();
903                assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
904                assert_eq!(deserialize.operands.len(), 1, "The number of operands is incorrect");
905                assert_eq!(
906                    deserialize.operands[0],
907                    Operand::Register(Register::Locator(0)),
908                    "The first operand is incorrect"
909                );
910                assert_eq!(&deserialize.operand_type, &source_type, "The operand type is incorrect");
911                assert_eq!(deserialize.destination, Register::Locator(1), "The destination register is incorrect");
912                assert_eq!(&deserialize.destination_type, destination_type, "The destination type is incorrect");
913            }
914        }
915    }
916
917    #[test]
918    fn test_parse() {
919        // Initialize an RNG.
920        let rng = &mut TestRng::default();
921
922        // Run the parser test for each variant.
923        run_parser_test::<{ DeserializeVariant::FromBits as u8 }>(rng);
924        run_parser_test::<{ DeserializeVariant::FromBitsRaw as u8 }>(rng);
925    }
926}