Skip to main content

snarkvm_circuit_program/data/literal/
from_bits.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 super::*;
17
18impl<A: Aleo> Literal<A> {
19    /// Initializes a new literal from a list of little-endian bits *without* trailing zeros.
20    pub fn from_bits_le(variant: &U8<A>, bits_le: &[Boolean<A>]) -> Self {
21        let literal = bits_le;
22        match *variant.eject_value() {
23            0 => Literal::Address(Address::from_bits_le(literal)),
24            1 => Literal::Boolean(Boolean::from_bits_le(literal)),
25            2 => Literal::Field(Field::from_bits_le(literal)),
26            3 => Literal::Group(Group::from_bits_le(literal)),
27            4 => Literal::I8(I8::from_bits_le(literal)),
28            5 => Literal::I16(I16::from_bits_le(literal)),
29            6 => Literal::I32(I32::from_bits_le(literal)),
30            7 => Literal::I64(I64::from_bits_le(literal)),
31            8 => Literal::I128(I128::from_bits_le(literal)),
32            9 => Literal::U8(U8::from_bits_le(literal)),
33            10 => Literal::U16(U16::from_bits_le(literal)),
34            11 => Literal::U32(U32::from_bits_le(literal)),
35            12 => Literal::U64(U64::from_bits_le(literal)),
36            13 => Literal::U128(U128::from_bits_le(literal)),
37            14 => Literal::Scalar(Scalar::from_bits_le(literal)),
38            15 => Literal::Signature(Box::new(Signature::from_bits_le(literal))),
39            16 => Literal::String(StringType::from_bits_le(literal)),
40            17 => Literal::Identifier(Box::new(IdentifierLiteral::from_bits_le(literal))),
41            18.. => A::halt(format!("Failed to initialize literal variant {} from bits (LE)", variant.eject_value())),
42        }
43    }
44
45    /// Initializes a new literal from a list of big-endian bits *without* leading zeros.
46    pub fn from_bits_be(variant: &U8<A>, bits_be: &[Boolean<A>]) -> Self {
47        let literal = bits_be;
48        match *variant.eject_value() {
49            0 => Literal::Address(Address::from_bits_be(literal)),
50            1 => Literal::Boolean(Boolean::from_bits_be(literal)),
51            2 => Literal::Field(Field::from_bits_be(literal)),
52            3 => Literal::Group(Group::from_bits_be(literal)),
53            4 => Literal::I8(I8::from_bits_be(literal)),
54            5 => Literal::I16(I16::from_bits_be(literal)),
55            6 => Literal::I32(I32::from_bits_be(literal)),
56            7 => Literal::I64(I64::from_bits_be(literal)),
57            8 => Literal::I128(I128::from_bits_be(literal)),
58            9 => Literal::U8(U8::from_bits_be(literal)),
59            10 => Literal::U16(U16::from_bits_be(literal)),
60            11 => Literal::U32(U32::from_bits_be(literal)),
61            12 => Literal::U64(U64::from_bits_be(literal)),
62            13 => Literal::U128(U128::from_bits_be(literal)),
63            14 => Literal::Scalar(Scalar::from_bits_be(literal)),
64            15 => Literal::Signature(Box::new(Signature::from_bits_be(literal))),
65            16 => Literal::String(StringType::from_bits_be(literal)),
66            17 => Literal::Identifier(Box::new(IdentifierLiteral::from_bits_be(literal))),
67            18.. => A::halt(format!("Failed to initialize literal variant {} from bits (BE))", variant.eject_value())),
68        }
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75    use crate::Circuit;
76    use console::{TestRng, Uniform};
77
78    const ITERATIONS: u32 = 10;
79
80    fn check_serialization(expected: Literal<Circuit>) {
81        // Success cases.
82        assert_eq!(
83            expected.eject_value(),
84            Literal::from_bits_le(&expected.variant(), &expected.to_bits_le()).eject_value()
85        );
86        assert_eq!(
87            expected.eject_value(),
88            Literal::from_bits_be(&expected.variant(), &expected.to_bits_be()).eject_value()
89        );
90
91        // // Failure cases.
92        // assert!(std::panic::catch_unwind(|| Literal::from_bits_le(&expected.variant(), &expected.to_bits_be()).eject_value()).is_err());
93        // Circuit::reset();
94        // assert!(std::panic::catch_unwind(|| Literal::from_bits_be(&expected.variant(), &expected.to_bits_le()).eject_value()).is_err());
95        Circuit::reset();
96    }
97
98    fn run_serialization_test(mode: Mode) {
99        let rng = &mut TestRng::default();
100
101        for _ in 0..ITERATIONS {
102            // Address
103            check_serialization(Literal::<Circuit>::Address(Address::new(mode, console::Address::rand(rng))));
104            // Boolean
105            check_serialization(Literal::<Circuit>::Boolean(Boolean::new(mode, Uniform::rand(rng))));
106            // Field
107            check_serialization(Literal::<Circuit>::Field(Field::new(mode, Uniform::rand(rng))));
108            // Group
109            check_serialization(Literal::<Circuit>::Group(Group::new(mode, Uniform::rand(rng))));
110            // I8
111            check_serialization(Literal::<Circuit>::I8(I8::new(mode, Uniform::rand(rng))));
112            // I16
113            check_serialization(Literal::<Circuit>::I16(I16::new(mode, Uniform::rand(rng))));
114            // I32
115            check_serialization(Literal::<Circuit>::I32(I32::new(mode, Uniform::rand(rng))));
116            // I64
117            check_serialization(Literal::<Circuit>::I64(I64::new(mode, Uniform::rand(rng))));
118            // I128
119            check_serialization(Literal::<Circuit>::I128(I128::new(mode, Uniform::rand(rng))));
120            // U8
121            check_serialization(Literal::<Circuit>::U8(U8::new(mode, Uniform::rand(rng))));
122            // U16
123            check_serialization(Literal::<Circuit>::U16(U16::new(mode, Uniform::rand(rng))));
124            // U32
125            check_serialization(Literal::<Circuit>::U32(U32::new(mode, Uniform::rand(rng))));
126            // U64
127            check_serialization(Literal::<Circuit>::U64(U64::new(mode, Uniform::rand(rng))));
128            // U128
129            check_serialization(Literal::<Circuit>::U128(U128::new(mode, Uniform::rand(rng))));
130            // Scalar
131            check_serialization(Literal::<Circuit>::Scalar(Scalar::new(mode, Uniform::rand(rng))));
132            // Signature
133            check_serialization(Literal::new(mode, console::Literal::sample(LiteralType::Signature, rng)));
134            // String
135            // Sample a random string. Take 1/4th to ensure we fit for all code points.
136            let string = rng.next_string(Circuit::MAX_STRING_BYTES / 4, false);
137            check_serialization(Literal::<Circuit>::String(StringType::new(mode, console::StringType::new(&string))));
138        }
139    }
140
141    #[test]
142    fn test_serialization_constant() {
143        run_serialization_test(Mode::Constant);
144    }
145
146    #[test]
147    fn test_serialization_public() {
148        run_serialization_test(Mode::Public);
149    }
150
151    #[test]
152    fn test_serialization_private() {
153        run_serialization_test(Mode::Private);
154    }
155}