snarkvm_console_program/data/plaintext/
from_bits.rs

1// Copyright 2024 Aleo Network Foundation
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 super::*;
17
18impl<N: Network> FromBits for Plaintext<N> {
19    /// Initializes a new plaintext from a list of little-endian bits *without* trailing zeros.
20    fn from_bits_le(bits_le: &[bool]) -> Result<Self> {
21        let bits = bits_le;
22
23        // The starting index used to create subsequent subslices of the `bits` slice.
24        let mut index = 0;
25
26        // Helper function to get the next n bits as a slice.
27        let mut next_bits = |n: usize| -> Result<&[bool]> {
28            // Safely procure a subslice with the length `n` starting at `index`.
29            let subslice = bits.get(index..index + n);
30            // Check if the range is within bounds.
31            if let Some(next_bits) = subslice {
32                // Move the starting index.
33                index += n;
34                // Return the subslice.
35                Ok(next_bits)
36            } else {
37                bail!("Insufficient bits");
38            }
39        };
40
41        let variant = next_bits(2)?;
42        let variant = [variant[0], variant[1]];
43
44        // Literal
45        if variant == [false, false] {
46            let literal_variant = u8::from_bits_le(next_bits(8)?)?;
47            let literal_size = u16::from_bits_le(next_bits(16)?)?;
48            let literal = Literal::from_bits_le(literal_variant, next_bits(literal_size as usize)?)?;
49
50            // Cache the plaintext bits, and return the literal.
51            Ok(Self::Literal(literal, OnceCell::with_value(bits_le.to_vec())))
52        }
53        // Struct
54        else if variant == [false, true] {
55            let num_members = u8::from_bits_le(next_bits(8)?)?;
56            if num_members as usize > N::MAX_STRUCT_ENTRIES {
57                bail!("Struct exceeds maximum of entries.");
58            }
59
60            let mut members = IndexMap::with_capacity(num_members as usize);
61            for _ in 0..num_members {
62                let identifier_size = u8::from_bits_le(next_bits(8)?)?;
63                let identifier = Identifier::from_bits_le(next_bits(identifier_size as usize)?)?;
64
65                let member_size = u16::from_bits_le(next_bits(16)?)?;
66                let value = Plaintext::from_bits_le(next_bits(member_size as usize)?)?;
67
68                if members.insert(identifier, value).is_some() {
69                    bail!("Duplicate identifier in struct.");
70                }
71            }
72
73            // Cache the plaintext bits, and return the struct.
74            Ok(Self::Struct(members, OnceCell::with_value(bits_le.to_vec())))
75        }
76        // Array
77        else if variant == [true, false] {
78            let num_elements = u32::from_bits_le(next_bits(32)?)?;
79            if num_elements as usize > N::MAX_ARRAY_ELEMENTS {
80                bail!("Array exceeds maximum of elements.");
81            }
82
83            let mut elements = Vec::with_capacity(num_elements as usize);
84            for _ in 0..num_elements {
85                let element_size = u16::from_bits_le(next_bits(16)?)?;
86                let element = Plaintext::from_bits_le(next_bits(element_size as usize)?)?;
87
88                elements.push(element);
89            }
90
91            // Cache the plaintext bits, and return the array.
92            Ok(Self::Array(elements, OnceCell::with_value(bits_le.to_vec())))
93        }
94        // Unknown variant.
95        else {
96            bail!("Unknown plaintext variant - {variant:?}");
97        }
98    }
99
100    /// Initializes a new plaintext from a list of big-endian bits *without* trailing zeros.
101    fn from_bits_be(bits_be: &[bool]) -> Result<Self> {
102        let bits = bits_be;
103
104        // The starting index used to create subsequent subslices of the `bits` slice.
105        let mut index = 0;
106
107        // Helper function to get the next n bits as a slice.
108        let mut next_bits = |n: usize| -> Result<&[bool]> {
109            // Safely procure a subslice with the length `n` starting at `index`.
110            let subslice = bits.get(index..index + n);
111            // Check if the range is within bounds.
112            if let Some(next_bits) = subslice {
113                // Move the starting index.
114                index += n;
115                // Return the subslice.
116                Ok(next_bits)
117            } else {
118                bail!("Insufficient bits");
119            }
120        };
121
122        let variant = next_bits(2)?;
123        let variant = [variant[0], variant[1]];
124
125        // Literal
126        if variant == [false, false] {
127            let literal_variant = u8::from_bits_be(next_bits(8)?)?;
128            let literal_size = u16::from_bits_be(next_bits(16)?)?;
129            let literal = Literal::from_bits_be(literal_variant, next_bits(literal_size as usize)?)?;
130
131            // Cache the plaintext bits, and return the literal.
132            Ok(Self::Literal(literal, OnceCell::with_value(bits_be.to_vec())))
133        }
134        // Struct
135        else if variant == [false, true] {
136            let num_members = u8::from_bits_be(next_bits(8)?)?;
137            if num_members as usize > N::MAX_STRUCT_ENTRIES {
138                bail!("Struct exceeds maximum of entries.");
139            }
140
141            let mut members = IndexMap::with_capacity(num_members as usize);
142            for _ in 0..num_members {
143                let identifier_size = u8::from_bits_be(next_bits(8)?)?;
144                let identifier = Identifier::from_bits_be(next_bits(identifier_size as usize)?)?;
145
146                let member_size = u16::from_bits_be(next_bits(16)?)?;
147                let value = Plaintext::from_bits_be(next_bits(member_size as usize)?)?;
148
149                if members.insert(identifier, value).is_some() {
150                    bail!("Duplicate identifier in struct.");
151                }
152            }
153
154            // Cache the plaintext bits, and return the struct.
155            Ok(Self::Struct(members, OnceCell::with_value(bits_be.to_vec())))
156        }
157        // Array
158        else if variant == [true, false] {
159            let num_elements = u32::from_bits_be(next_bits(32)?)?;
160            if num_elements as usize > N::MAX_ARRAY_ELEMENTS {
161                bail!("Array exceeds maximum of elements.");
162            }
163
164            let mut elements = Vec::with_capacity(num_elements as usize);
165            for _ in 0..num_elements {
166                let element_size = u16::from_bits_be(next_bits(16)?)?;
167                let element = Plaintext::from_bits_be(next_bits(element_size as usize)?)?;
168
169                elements.push(element);
170            }
171
172            // Cache the plaintext bits, and return the array.
173            Ok(Self::Array(elements, OnceCell::with_value(bits_be.to_vec())))
174        }
175        // Unknown variant.
176        else {
177            bail!("Unknown plaintext variant - {variant:?}");
178        }
179    }
180}