use ark_ff::Field;
use ark_relations::gr1cs::{ConstraintSystemRef, SynthesisError};
use ark_std::vec::Vec;
pub trait GR1CSVar<F: Field> {
type Value: core::fmt::Debug + Eq + Clone;
fn cs(&self) -> ConstraintSystemRef<F>;
fn is_constant(&self) -> bool {
self.cs().is_none()
}
fn value(&self) -> Result<Self::Value, SynthesisError>;
}
impl<F: Field, T: GR1CSVar<F>> GR1CSVar<F> for [T] {
type Value = Vec<T::Value>;
fn cs(&self) -> ConstraintSystemRef<F> {
let mut result = ConstraintSystemRef::None;
for var in self {
result = var.cs().or(result);
}
result
}
fn value(&self) -> Result<Self::Value, SynthesisError> {
let mut result = Vec::new();
for var in self {
result.push(var.value()?);
}
Ok(result)
}
}
impl<'a, F: Field, T: 'a + GR1CSVar<F>> GR1CSVar<F> for &'a T {
type Value = T::Value;
fn cs(&self) -> ConstraintSystemRef<F> {
(*self).cs()
}
fn value(&self) -> Result<Self::Value, SynthesisError> {
(*self).value()
}
}
impl<F: Field, T: GR1CSVar<F>, const N: usize> GR1CSVar<F> for [T; N] {
type Value = [T::Value; N];
fn cs(&self) -> ConstraintSystemRef<F> {
let mut result = ConstraintSystemRef::None;
for var in self {
result = var.cs().or(result);
}
result
}
fn value(&self) -> Result<Self::Value, SynthesisError> {
Ok(core::array::from_fn(|i| self[i].value().unwrap()))
}
}
impl<F: Field> GR1CSVar<F> for () {
type Value = ();
fn cs(&self) -> ConstraintSystemRef<F> {
ConstraintSystemRef::None
}
fn value(&self) -> Result<Self::Value, SynthesisError> {
Ok(())
}
}