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));