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/// Unary operator for converting to raw bits.
42pub trait ToBitsRaw: ToBits {
43 /// Returns the little-endian bits without variant or identifier bits of the circuit.
44 fn to_bits_raw_le(&self) -> Vec<Self::Boolean> {
45 let mut bits = vec![];
46 self.write_bits_raw_le(&mut bits);
47 bits
48 }
49
50 fn write_bits_raw_le(&self, vec: &mut Vec<Self::Boolean>);
51
52 /// Returns the bits-endian bits without variant or identifier bits of the circuit.
53 fn to_bits_raw_be(&self) -> Vec<Self::Boolean> {
54 let mut bits = vec![];
55 self.write_bits_raw_be(&mut bits);
56 bits
57 }
58
59 fn write_bits_raw_be(&self, vec: &mut Vec<Self::Boolean>);
60}
61
62/********************/
63/****** Arrays ******/
64/********************/
65
66impl<C: ToBits<Boolean = B>, B: BooleanTrait> ToBits for Vec<C> {
67 type Boolean = B;
68
69 /// A helper method to return a concatenated list of little-endian bits from the circuits.
70 #[inline]
71 fn write_bits_le(&self, vec: &mut Vec<Self::Boolean>) {
72 // The vector is order-preserving, meaning the first circuit in is the first circuit bits out.
73 self.as_slice().write_bits_le(vec);
74 }
75
76 /// A helper method to return a concatenated list of big-endian bits from the circuits.
77 #[inline]
78 fn write_bits_be(&self, vec: &mut Vec<Self::Boolean>) {
79 // The vector is order-preserving, meaning the first circuit in is the first circuit bits out.
80 self.as_slice().write_bits_be(vec);
81 }
82}
83
84impl<C: ToBits<Boolean = B>, B: BooleanTrait, const N: usize> ToBits for [C; N] {
85 type Boolean = B;
86
87 /// A helper method to return a concatenated list of little-endian bits from the circuits.
88 #[inline]
89 fn write_bits_le(&self, vec: &mut Vec<Self::Boolean>) {
90 // The slice is order-preserving, meaning the first circuit in is the first circuit bits out.
91 self.as_slice().write_bits_le(vec);
92 }
93
94 /// A helper method to return a concatenated list of big-endian bits from the circuits.
95 #[inline]
96 fn write_bits_be(&self, vec: &mut Vec<Self::Boolean>) {
97 // The slice is order-preserving, meaning the first circuit in is the first circuit bits out.
98 self.as_slice().write_bits_be(vec);
99 }
100}
101
102impl<C: ToBits<Boolean = B>, B: BooleanTrait> ToBits for &[C] {
103 type Boolean = B;
104
105 /// A helper method to return a concatenated list of little-endian bits from the circuits.
106 #[inline]
107 fn write_bits_le(&self, vec: &mut Vec<Self::Boolean>) {
108 // The slice is order-preserving, meaning the first circuit in is the first circuit bits out.
109 for elem in self.iter() {
110 elem.write_bits_le(vec);
111 }
112 }
113
114 /// A helper method to return a concatenated list of big-endian bits from the circuits.
115 #[inline]
116 fn write_bits_be(&self, vec: &mut Vec<Self::Boolean>) {
117 // The slice is order-preserving, meaning the first circuit in is the first circuit bits out.
118 for elem in self.iter() {
119 elem.write_bits_be(vec);
120 }
121 }
122}
123
124impl<C: ToBitsRaw<Boolean = B>, B: BooleanTrait> ToBitsRaw for Vec<C> {
125 /// A helper method to return a concatenated list of little-endian bits without variant or identifier bits from the circuits.
126 #[inline]
127 fn write_bits_raw_le(&self, vec: &mut Vec<Self::Boolean>) {
128 // The vector is order-preserving, meaning the first circuit in is the first circuit bits out.
129 self.as_slice().write_bits_raw_le(vec);
130 }
131
132 /// A helper method to return a concatenated list of bits-endian bits without variant or identifier bits from the circuits.
133 #[inline]
134 fn write_bits_raw_be(&self, vec: &mut Vec<Self::Boolean>) {
135 // The vector is order-preserving, meaning the first circuit in is the first circuit bits out.
136 self.as_slice().write_bits_raw_be(vec);
137 }
138}
139
140impl<C: ToBitsRaw<Boolean = B>, B: BooleanTrait, const N: usize> ToBitsRaw for [C; N] {
141 /// A helper method to return a concatenated list of little-endian bits without variant or identifier bits from the circuits.
142 #[inline]
143 fn write_bits_raw_le(&self, vec: &mut Vec<Self::Boolean>) {
144 // The slice is order-preserving, meaning the first circuit in is the first circuit bits out.
145 self.as_slice().write_bits_raw_le(vec);
146 }
147
148 /// A helper method to return a concatenated list of bits-endian bits without variant or identifier bits from the circuits.
149 #[inline]
150 fn write_bits_raw_be(&self, vec: &mut Vec<Self::Boolean>) {
151 // The slice is order-preserving, meaning the first circuit in is the first circuit bits out.
152 self.as_slice().write_bits_raw_be(vec);
153 }
154}
155
156impl<C: ToBitsRaw<Boolean = B>, B: BooleanTrait> ToBitsRaw for &[C] {
157 /// A helper method to return a concatenated list of little-endian bits without variant or identifier bits from the circuits.
158 #[inline]
159 fn write_bits_raw_le(&self, vec: &mut Vec<Self::Boolean>) {
160 // The slice is order-preserving, meaning the first circuit in is the first circuit bits out.
161 for elem in self.iter() {
162 elem.write_bits_raw_le(vec);
163 }
164 }
165
166 /// A helper method to return a concatenated list of bits-endian bits without variant or identifier bits from the circuits.
167 #[inline]
168 fn write_bits_raw_be(&self, vec: &mut Vec<Self::Boolean>) {
169 // The slice is order-preserving, meaning the first circuit in is the first circuit bits out.
170 for elem in self.iter() {
171 elem.write_bits_raw_be(vec);
172 }
173 }
174}
175
176/********************/
177/****** Tuples ******/
178/********************/
179
180/// A helper macro to implement `ToBits` for a tuple of `ToBits` circuits.
181macro_rules! to_bits_tuple {
182 (($t0:ident, $i0:tt), $(($ty:ident, $idx:tt)),+) => {
183 impl<B: BooleanTrait, $t0: ToBits<Boolean = B>, $($ty: ToBits<Boolean = B>),+> ToBits for ($t0, $($ty),+) {
184 type Boolean = B;
185
186 /// A helper method to return a concatenated list of little-endian bits from the circuits.
187 #[inline]
188 fn write_bits_le(&self, vec: &mut Vec<Self::Boolean>) {
189 // The tuple is order-preserving, meaning the first circuit in is the first circuit bits out.
190 (&self).write_bits_le(vec);
191 }
192
193 /// A helper method to return a concatenated list of big-endian bits from the circuits.
194 #[inline]
195 fn write_bits_be(&self, vec: &mut Vec<Self::Boolean>) {
196 // The tuple is order-preserving, meaning the first circuit in is the first circuit bits out.
197 (&self).write_bits_be(vec);
198 }
199 }
200
201 impl<'a, B: BooleanTrait, $t0: ToBits<Boolean = B>, $($ty: ToBits<Boolean = B>),+> ToBits for &'a ($t0, $($ty),+) {
202 type Boolean = B;
203
204 /// A helper method to return a concatenated list of little-endian bits from the circuits.
205 #[inline]
206 fn write_bits_le(&self, vec: &mut Vec<Self::Boolean>) {
207 // The tuple is order-preserving, meaning the first circuit in is the first circuit bits out.
208 self.$i0.write_bits_le(vec);
209 $(self.$idx.write_bits_le(vec);)+
210 }
211
212 /// A helper method to return a concatenated list of big-endian bits from the circuits.
213 #[inline]
214 fn write_bits_be(&self, vec: &mut Vec<Self::Boolean>) {
215 // The tuple is order-preserving, meaning the first circuit in is the first circuit bits out.
216 self.$i0.write_bits_be(vec);
217 $(self.$idx.write_bits_be(vec);)+
218 }
219 }
220
221 impl<B: BooleanTrait, $t0: ToBitsRaw<Boolean = B>, $($ty: ToBitsRaw<Boolean = B>),+> ToBitsRaw for ($t0, $($ty),+) {
222 /// A helper method to return a concatenated list of little-endian bits without variant or identifier bits from the circuits.
223 #[inline]
224 fn write_bits_raw_le(&self, vec: &mut Vec<Self::Boolean>) {
225 // The tuple is order-preserving, meaning the first circuit in is the first circuit bits out.
226 (&self).write_bits_raw_le(vec);
227 }
228
229 /// A helper method to return a concatenated list of bits-endian bits without variant or identifier bits from the circuits.
230 #[inline]
231 fn write_bits_raw_be(&self, vec: &mut Vec<Self::Boolean>) {
232 // The tuple is order-preserving, meaning the first circuit in is the first circuit bits out.
233 (&self).write_bits_raw_be(vec);
234 }
235 }
236
237 impl<'a, B: BooleanTrait, $t0: ToBitsRaw<Boolean = B>, $($ty: ToBitsRaw<Boolean = B>),+> ToBitsRaw for &'a ($t0, $($ty),+) {
238 /// A helper method to return a concatenated list of little-endian bits without variant or identifier bits from the circuits.
239 #[inline]
240 fn write_bits_raw_le(&self, vec: &mut Vec<Self::Boolean>) {
241 // The tuple is order-preserving, meaning the first circuit in is the first circuit bits out.
242 self.$i0.write_bits_raw_le(vec);
243 $(self.$idx.write_bits_raw_le(vec);)+
244 }
245
246 /// A helper method to return a concatenated list of bits-endian bits without variant or identifier bits from the circuits.
247 #[inline]
248 fn write_bits_raw_be(&self, vec: &mut Vec<Self::Boolean>) {
249 // The tuple is order-preserving, meaning the first circuit in is the first circuit bits out.
250 self.$i0.write_bits_raw_be(vec);
251 $(self.$idx.write_bits_raw_be(vec);)+
252 }
253 }
254 }
255}
256
257to_bits_tuple!((C0, 0), (C1, 1));
258to_bits_tuple!((C0, 0), (C1, 1), (C2, 2));
259to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3));
260to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4));
261to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5));
262to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6));
263to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7));
264to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8));
265to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8), (C9, 9));
266to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8), (C9, 9), (C10, 10));