snarkvm_circuit_environment/traits/
to_bits.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::BooleanTrait;
17
18/// Unary operator for converting to bits.
19pub trait ToBits {
20    type Boolean: BooleanTrait;
21
22    /// Returns the little-endian bits of the circuit.
23    fn to_bits_le(&self) -> Vec<Self::Boolean> {
24        let mut bits = vec![];
25        self.write_bits_le(&mut bits);
26        bits
27    }
28
29    fn write_bits_le(&self, vec: &mut Vec<Self::Boolean>);
30
31    /// Returns the big-endian bits of the circuit.
32    fn to_bits_be(&self) -> Vec<Self::Boolean> {
33        let mut bits = vec![];
34        self.write_bits_be(&mut bits);
35        bits
36    }
37
38    fn write_bits_be(&self, vec: &mut Vec<Self::Boolean>);
39}
40
41/********************/
42/****** Arrays ******/
43/********************/
44
45impl<C: ToBits<Boolean = B>, B: BooleanTrait> ToBits for Vec<C> {
46    type Boolean = B;
47
48    /// A helper method to return a concatenated list of little-endian bits from the circuits.
49    #[inline]
50    fn write_bits_le(&self, vec: &mut Vec<Self::Boolean>) {
51        // The vector is order-preserving, meaning the first circuit in is the first circuit bits out.
52        self.as_slice().write_bits_le(vec);
53    }
54
55    /// A helper method to return a concatenated list of big-endian bits from the circuits.
56    #[inline]
57    fn write_bits_be(&self, vec: &mut Vec<Self::Boolean>) {
58        // The vector is order-preserving, meaning the first circuit in is the first circuit bits out.
59        self.as_slice().write_bits_be(vec);
60    }
61}
62
63impl<C: ToBits<Boolean = B>, B: BooleanTrait, const N: usize> ToBits for [C; N] {
64    type Boolean = B;
65
66    /// A helper method to return a concatenated list of little-endian bits from the circuits.
67    #[inline]
68    fn write_bits_le(&self, vec: &mut Vec<Self::Boolean>) {
69        // The slice is order-preserving, meaning the first circuit in is the first circuit bits out.
70        self.as_slice().write_bits_le(vec);
71    }
72
73    /// A helper method to return a concatenated list of big-endian bits from the circuits.
74    #[inline]
75    fn write_bits_be(&self, vec: &mut Vec<Self::Boolean>) {
76        // The slice is order-preserving, meaning the first circuit in is the first circuit bits out.
77        self.as_slice().write_bits_be(vec);
78    }
79}
80
81impl<C: ToBits<Boolean = B>, B: BooleanTrait> ToBits for &[C] {
82    type Boolean = B;
83
84    /// A helper method to return a concatenated list of little-endian bits from the circuits.
85    #[inline]
86    fn write_bits_le(&self, vec: &mut Vec<Self::Boolean>) {
87        // The slice is order-preserving, meaning the first circuit in is the first circuit bits out.
88        for elem in self.iter() {
89            elem.write_bits_le(vec);
90        }
91    }
92
93    /// A helper method to return a concatenated list of big-endian bits from the circuits.
94    #[inline]
95    fn write_bits_be(&self, vec: &mut Vec<Self::Boolean>) {
96        // The slice is order-preserving, meaning the first circuit in is the first circuit bits out.
97        for elem in self.iter() {
98            elem.write_bits_be(vec);
99        }
100    }
101}
102
103/********************/
104/****** Tuples ******/
105/********************/
106
107/// A helper macro to implement `ToBits` for a tuple of `ToBits` circuits.
108macro_rules! to_bits_tuple {
109    (($t0:ident, $i0:tt), $(($ty:ident, $idx:tt)),+) => {
110        impl<B: BooleanTrait, $t0: ToBits<Boolean = B>, $($ty: ToBits<Boolean = B>),+> ToBits for ($t0, $($ty),+) {
111            type Boolean = B;
112
113            /// A helper method to return a concatenated list of little-endian bits from the circuits.
114            #[inline]
115            fn write_bits_le(&self, vec: &mut Vec<Self::Boolean>) {
116                // The tuple is order-preserving, meaning the first circuit in is the first circuit bits out.
117                (&self).write_bits_le(vec);
118            }
119
120            /// A helper method to return a concatenated list of big-endian bits from the circuits.
121            #[inline]
122            fn write_bits_be(&self, vec: &mut Vec<Self::Boolean>) {
123                // The tuple is order-preserving, meaning the first circuit in is the first circuit bits out.
124                (&self).write_bits_be(vec);
125            }
126        }
127
128        impl<'a, B: BooleanTrait, $t0: ToBits<Boolean = B>, $($ty: ToBits<Boolean = B>),+> ToBits for &'a ($t0, $($ty),+) {
129            type Boolean = B;
130
131            /// A helper method to return a concatenated list of little-endian bits from the circuits.
132            #[inline]
133            fn write_bits_le(&self, vec: &mut Vec<Self::Boolean>) {
134                // The tuple is order-preserving, meaning the first circuit in is the first circuit bits out.
135                self.$i0.write_bits_le(vec);
136                $(self.$idx.write_bits_le(vec);)+
137            }
138
139            /// A helper method to return a concatenated list of big-endian bits from the circuits.
140            #[inline]
141            fn write_bits_be(&self, vec: &mut Vec<Self::Boolean>) {
142                // The tuple is order-preserving, meaning the first circuit in is the first circuit bits out.
143                self.$i0.write_bits_be(vec);
144                $(self.$idx.write_bits_be(vec);)+
145            }
146        }
147    }
148}
149
150to_bits_tuple!((C0, 0), (C1, 1));
151to_bits_tuple!((C0, 0), (C1, 1), (C2, 2));
152to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3));
153to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4));
154to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5));
155to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6));
156to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7));
157to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8));
158to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8), (C9, 9));
159to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8), (C9, 9), (C10, 10));