ark_r1cs_std/
convert.rs

1use ark_ff::Field;
2use ark_relations::r1cs::SynthesisError;
3use ark_std::vec::Vec;
4
5use crate::{boolean::Boolean, uint8::UInt8};
6
7/// Specifies constraints for conversion to a little-endian bit representation
8/// of `self`.
9pub trait ToBitsGadget<F: Field> {
10    /// Outputs the canonical little-endian bit-wise representation of `self`.
11    ///
12    /// This is the correct default for 99% of use cases.
13    fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError>;
14
15    /// Outputs a possibly non-unique little-endian bit-wise representation of
16    /// `self`.
17    ///
18    /// If you're not absolutely certain that your usecase can get away with a
19    /// non-canonical representation, please use `self.to_bits()` instead.
20    fn to_non_unique_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
21        self.to_bits_le()
22    }
23
24    /// Outputs the canonical big-endian bit-wise representation of `self`.
25    fn to_bits_be(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
26        let mut res = self.to_bits_le()?;
27        res.reverse();
28        Ok(res)
29    }
30
31    /// Outputs a possibly non-unique big-endian bit-wise representation of
32    /// `self`.
33    fn to_non_unique_bits_be(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
34        let mut res = self.to_non_unique_bits_le()?;
35        res.reverse();
36        Ok(res)
37    }
38}
39
40impl<F: Field> ToBitsGadget<F> for Boolean<F> {
41    fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
42        Ok(vec![self.clone()])
43    }
44}
45
46impl<F: Field> ToBitsGadget<F> for [Boolean<F>] {
47    /// Outputs `self`.
48    fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
49        Ok(self.to_vec())
50    }
51}
52
53impl<F: Field, T> ToBitsGadget<F> for Vec<T>
54where
55    [T]: ToBitsGadget<F>,
56{
57    fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
58        self.as_slice().to_bits_le().map(|v| v.to_vec())
59    }
60
61    fn to_non_unique_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
62        self.as_slice().to_non_unique_bits_le().map(|v| v.to_vec())
63    }
64}
65
66/// Specifies constraints for conversion to a little-endian byte representation
67/// of `self`.
68pub trait ToBytesGadget<F: Field> {
69    /// Outputs a canonical, little-endian, byte decomposition of `self`.
70    ///
71    /// This is the correct default for 99% of use cases.
72    fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError>;
73
74    /// Outputs a possibly non-unique byte decomposition of `self`.
75    ///
76    /// If you're not absolutely certain that your usecase can get away with a
77    /// non-canonical representation, please use `self.to_bytes_le(cs)` instead.
78    fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
79        self.to_bytes_le()
80    }
81}
82
83impl<'a, F: Field, T: 'a + ToBytesGadget<F>> ToBytesGadget<F> for &'a T {
84    fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
85        (*self).to_bytes_le()
86    }
87
88    fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
89        (*self).to_non_unique_bytes_le()
90    }
91}
92
93impl<T: ToBytesGadget<F>, F: Field> ToBytesGadget<F> for [T] {
94    fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
95        let mut bytes = Vec::new();
96        for elem in self {
97            let elem = elem.to_bytes_le()?;
98            bytes.extend_from_slice(&elem);
99            // Make sure that there's enough capacity to avoid reallocations.
100            bytes.reserve(elem.len() * (self.len() - 1));
101        }
102        Ok(bytes)
103    }
104
105    fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
106        let mut bytes = Vec::new();
107        for elem in self {
108            let elem = elem.to_non_unique_bytes_le()?;
109            bytes.extend_from_slice(&elem);
110            // Make sure that there's enough capacity to avoid reallocations.
111            bytes.reserve(elem.len() * (self.len() - 1));
112        }
113        Ok(bytes)
114    }
115}
116
117impl<T: ToBytesGadget<F>, F: Field> ToBytesGadget<F> for Vec<T> {
118    fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
119        self.as_slice().to_bytes_le()
120    }
121
122    fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
123        self.as_slice().to_non_unique_bytes_le()
124    }
125}
126
127impl<T: ToBytesGadget<F>, F: Field, const N: usize> ToBytesGadget<F> for [T; N] {
128    fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
129        self.as_slice().to_bytes_le()
130    }
131
132    fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
133        self.as_slice().to_non_unique_bytes_le()
134    }
135}
136
137impl<F: Field> ToBytesGadget<F> for () {
138    fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
139        Ok(Vec::new())
140    }
141
142    fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
143        Ok(Vec::new())
144    }
145}
146
147/// Specifies how to convert a variable of type `Self` to variables of
148/// type `FpVar<ConstraintF>`
149pub trait ToConstraintFieldGadget<ConstraintF: ark_ff::PrimeField> {
150    /// Converts `self` to `FpVar<ConstraintF>` variables.
151    fn to_constraint_field(
152        &self,
153    ) -> Result<Vec<crate::fields::fp::FpVar<ConstraintF>>, ark_relations::r1cs::SynthesisError>;
154}