use crate::*;
use snarkvm_fields::PrimeField;
use std::{mem, sync::Arc};
#[derive(Debug, Default, Hash)]
pub(crate) struct Counter<F: PrimeField> {
scope: Scope,
constraints: Vec<Arc<Constraint<F>>>,
constants: u64,
public: u64,
private: u64,
nonzeros: (u64, u64, u64),
parents: Vec<(Scope, Vec<Arc<Constraint<F>>>, u64, u64, u64, (u64, u64, u64))>,
}
impl<F: PrimeField> Counter<F> {
pub(crate) fn push<S: Into<String>>(&mut self, name: S) -> Result<(), String> {
let name = name.into();
match name.contains('.') {
true => Err("Scope names cannot contain periods (\".\")".to_string()),
false => {
let scope = match self.scope.is_empty() {
true => name,
false => format!("{}.{}", self.scope, name),
};
self.parents.push((
self.scope.clone(),
mem::take(&mut self.constraints),
self.constants,
self.public,
self.private,
self.nonzeros,
));
self.scope = scope;
self.constants = 0;
self.public = 0;
self.private = 0;
self.nonzeros = (0, 0, 0);
Ok(())
}
}
}
pub(crate) fn pop<S: Into<String>>(&mut self, name: S) -> Result<(), String> {
let (_previous_scope, current_scope) = match self.scope.rsplit_once('.') {
Some((previous_scope, current_scope)) => (previous_scope, current_scope),
None => ("", self.scope.as_str()),
};
match current_scope == name.into() {
true => {
if let Some((scope, constraints, constants, public, private, nonzeros)) = self.parents.pop() {
self.scope = scope;
self.constraints = constraints;
self.constants = constants;
self.public = public;
self.private = private;
self.nonzeros = nonzeros;
}
}
false => {
return Err("Mismatching scope. Scopes must return in the reverse order they are created".to_string());
}
}
Ok(())
}
pub(crate) fn add_constraint(&mut self, constraint: Arc<Constraint<F>>) {
let (a_nonzeros, b_nonzeros, c_nonzeros) = constraint.num_nonzeros();
self.nonzeros.0 += a_nonzeros;
self.nonzeros.1 += b_nonzeros;
self.nonzeros.2 += c_nonzeros;
self.constraints.push(constraint);
}
pub(crate) fn is_satisfied_in_scope(&self) -> bool {
self.constraints.iter().all(|constraint| constraint.is_satisfied())
}
pub(crate) fn scope(&self) -> Scope {
self.scope.clone()
}
pub(crate) fn increment_constant(&mut self) {
self.constants += 1;
}
pub(crate) fn increment_public(&mut self) {
self.public += 1;
}
pub(crate) fn increment_private(&mut self) {
self.private += 1;
}
pub(crate) fn num_constants_in_scope(&self) -> u64 {
self.constants
}
pub(crate) fn num_public_in_scope(&self) -> u64 {
self.public
}
pub(crate) fn num_private_in_scope(&self) -> u64 {
self.private
}
pub(crate) fn num_constraints_in_scope(&self) -> u64 {
self.constraints.len() as u64
}
pub(crate) fn num_nonzeros_in_scope(&self) -> (u64, u64, u64) {
self.nonzeros
}
}