use super::*;
use snarkvm_circuit_types_field::Field;
impl<E: Environment> ToFields for StringType<E> {
type Field = Field<E>;
fn to_fields(&self) -> Vec<Self::Field> {
self.to_bits_le().chunks(E::BaseField::size_in_data_bits()).map(Field::from_bits_le).collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
use snarkvm_circuit_environment::Circuit;
use snarkvm_utilities::{FromBytes, bytes_from_bits_le};
fn native_string_to_fields(string: &str) -> Vec<console::Field<<Circuit as Environment>::Network>> {
string
.to_string()
.to_bits_le()
.chunks(<Circuit as Environment>::BaseField::size_in_data_bits())
.map(|chunk| {
let mut chunk = chunk.to_vec();
chunk.resize(<Circuit as Environment>::BaseField::size_in_bits(), false);
let chunk = bytes_from_bits_le(&chunk);
console::Field::new(<Circuit as Environment>::BaseField::from_bytes_le(&chunk).unwrap())
})
.collect()
}
fn check_to_fields(
name: &str,
expected: &[console::Field<<Circuit as Environment>::Network>],
candidate: &StringType<Circuit>,
num_constants: u64,
num_public: u64,
num_private: u64,
num_constraints: u64,
) {
Circuit::scope(name, || {
let candidate = candidate.to_fields();
assert_eq!(expected.len(), candidate.len());
assert_scope!(num_constants, num_public, num_private, num_constraints);
for (expected_field, candidate_field) in expected.iter().zip_eq(&candidate) {
assert_eq!(expected_field, &candidate_field.eject_value());
}
});
Circuit::reset();
}
#[test]
fn test_to_fields_constant() {
let rng = &mut TestRng::default();
let given = rng.next_string(Circuit::MAX_STRING_BYTES / 4, false);
let expected = native_string_to_fields(&given);
let candidate = StringType::<Circuit>::new(Mode::Constant, console::StringType::new(&given));
check_to_fields("Constant", &expected, &candidate, 0, 0, 0, 0);
}
#[test]
fn test_to_fields_public() {
let rng = &mut TestRng::default();
let given = rng.next_string(Circuit::MAX_STRING_BYTES / 4, false);
let expected = native_string_to_fields(&given);
let candidate = StringType::<Circuit>::new(Mode::Public, console::StringType::new(&given));
check_to_fields("Public", &expected, &candidate, 0, 0, 0, 0);
}
#[test]
fn test_to_fields_private() {
let rng = &mut TestRng::default();
let given = rng.next_string(Circuit::MAX_STRING_BYTES / 4, false);
let expected = native_string_to_fields(&given);
let candidate = StringType::<Circuit>::new(Mode::Private, console::StringType::new(&given));
check_to_fields("Private", &expected, &candidate, 0, 0, 0, 0);
}
}