use crate::Vec; use algebra::Field; use core::borrow::Borrow; use r1cs_core::{Namespace, SynthesisError}; #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Copy, Clone)] pub enum AllocationMode { Constant = 0, Input = 1, Witness = 2, } impl AllocationMode { // Outputs the maximum according to the relation `Constant < Input < Witness`. pub fn max(&self, other: Self) -> Self { use AllocationMode::*; match (self, other) { (Constant, _) => other, (Input, Constant) => *self, (Input, _) => other, (Witness, _) => *self, } } } pub trait AllocVar where Self: Sized, V: ?Sized, { fn new_variable>( cs: impl Into>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result; #[tracing::instrument(target = "r1cs", skip(cs, t))] fn new_constant( cs: impl Into>, t: impl Borrow, ) -> Result { Self::new_variable(cs, || Ok(t), AllocationMode::Constant) } #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_input>( cs: impl Into>, f: impl FnOnce() -> Result, ) -> Result { Self::new_variable(cs, f, AllocationMode::Input) } #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_witness>( cs: impl Into>, f: impl FnOnce() -> Result, ) -> Result { Self::new_variable(cs, f, AllocationMode::Witness) } } impl> AllocVar<[I], F> for Vec { fn new_variable>( cs: impl Into>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { let ns = cs.into(); let cs = ns.cs(); let mut vec = Vec::new(); for value in f()?.borrow().iter() { vec.push(A::new_variable(cs.clone(), || Ok(value), mode)?); } Ok(vec) } }