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