use std::{cmp, collections::HashSet, fmt};
use ff::Field;
pub use super::table_layouter::TableLayouter;
use super::{Cell, RegionIndex, Value};
use crate::{
plonk::{Advice, Any, Column, Error, Fixed, Instance, Selector},
utils::rational::Rational,
};
pub trait SyncDeps {}
impl<T> SyncDeps for T {}
pub trait RegionLayouter<F: Field>: fmt::Debug + SyncDeps {
fn enable_selector<'v>(
&'v mut self,
annotation: &'v (dyn Fn() -> String + 'v),
selector: &Selector,
offset: usize,
) -> Result<(), Error>;
fn name_column<'v>(
&'v mut self,
annotation: &'v (dyn Fn() -> String + 'v),
column: Column<Any>,
);
fn assign_advice<'v>(
&'v mut self,
annotation: &'v (dyn Fn() -> String + 'v),
column: Column<Advice>,
offset: usize,
to: &'v mut (dyn FnMut() -> Value<Rational<F>> + 'v),
) -> Result<Cell, Error>;
fn assign_advice_from_constant<'v>(
&'v mut self,
annotation: &'v (dyn Fn() -> String + 'v),
column: Column<Advice>,
offset: usize,
constant: Rational<F>,
) -> Result<Cell, Error>;
fn assign_advice_from_instance<'v>(
&mut self,
annotation: &'v (dyn Fn() -> String + 'v),
instance: Column<Instance>,
row: usize,
advice: Column<Advice>,
offset: usize,
) -> Result<(Cell, Value<F>), Error>;
fn instance_value(&mut self, instance: Column<Instance>, row: usize)
-> Result<Value<F>, Error>;
fn assign_fixed<'v>(
&'v mut self,
annotation: &'v (dyn Fn() -> String + 'v),
column: Column<Fixed>,
offset: usize,
to: &'v mut (dyn FnMut() -> Value<Rational<F>> + 'v),
) -> Result<Cell, Error>;
fn constrain_constant(&mut self, cell: Cell, constant: Rational<F>) -> Result<(), Error>;
fn constrain_equal(&mut self, left: Cell, right: Cell) -> Result<(), Error>;
}
#[derive(Clone, Debug)]
pub struct RegionShape {
pub(super) region_index: RegionIndex,
pub(super) columns: HashSet<RegionColumn>,
pub(super) row_count: usize,
}
#[derive(Eq, PartialEq, Copy, Clone, Debug, Hash)]
pub enum RegionColumn {
Column(Column<Any>),
Selector(Selector),
}
impl From<Column<Any>> for RegionColumn {
fn from(column: Column<Any>) -> RegionColumn {
RegionColumn::Column(column)
}
}
impl From<Selector> for RegionColumn {
fn from(selector: Selector) -> RegionColumn {
RegionColumn::Selector(selector)
}
}
impl Ord for RegionColumn {
fn cmp(&self, other: &Self) -> cmp::Ordering {
match (self, other) {
(Self::Column(ref a), Self::Column(ref b)) => a.cmp(b),
(Self::Selector(ref a), Self::Selector(ref b)) => a.0.cmp(&b.0),
(Self::Column(_), Self::Selector(_)) => cmp::Ordering::Less,
(Self::Selector(_), Self::Column(_)) => cmp::Ordering::Greater,
}
}
}
impl PartialOrd for RegionColumn {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl RegionShape {
pub fn new(region_index: RegionIndex) -> Self {
RegionShape {
region_index,
columns: HashSet::default(),
row_count: 0,
}
}
pub fn region_index(&self) -> RegionIndex {
self.region_index
}
pub fn columns(&self) -> &HashSet<RegionColumn> {
&self.columns
}
pub fn row_count(&self) -> usize {
self.row_count
}
}
impl<F: Field> RegionLayouter<F> for RegionShape {
fn enable_selector<'v>(
&'v mut self,
_: &'v (dyn Fn() -> String + 'v),
selector: &Selector,
offset: usize,
) -> Result<(), Error> {
self.columns.insert((*selector).into());
self.row_count = cmp::max(self.row_count, offset + 1);
Ok(())
}
fn assign_advice<'v>(
&'v mut self,
_: &'v (dyn Fn() -> String + 'v),
column: Column<Advice>,
offset: usize,
_to: &'v mut (dyn FnMut() -> Value<Rational<F>> + 'v),
) -> Result<Cell, Error> {
self.columns.insert(Column::<Any>::from(column).into());
self.row_count = cmp::max(self.row_count, offset + 1);
Ok(Cell {
region_index: self.region_index,
row_offset: offset,
column: column.into(),
})
}
fn assign_advice_from_constant<'v>(
&'v mut self,
annotation: &'v (dyn Fn() -> String + 'v),
column: Column<Advice>,
offset: usize,
constant: Rational<F>,
) -> Result<Cell, Error> {
self.assign_advice(annotation, column, offset, &mut || Value::known(constant))
}
fn assign_advice_from_instance<'v>(
&mut self,
_: &'v (dyn Fn() -> String + 'v),
_: Column<Instance>,
_: usize,
advice: Column<Advice>,
offset: usize,
) -> Result<(Cell, Value<F>), Error> {
self.columns.insert(Column::<Any>::from(advice).into());
self.row_count = cmp::max(self.row_count, offset + 1);
Ok((
Cell {
region_index: self.region_index,
row_offset: offset,
column: advice.into(),
},
Value::unknown(),
))
}
fn instance_value(
&mut self,
_instance: Column<Instance>,
_row: usize,
) -> Result<Value<F>, Error> {
Ok(Value::unknown())
}
fn assign_fixed<'v>(
&'v mut self,
_: &'v (dyn Fn() -> String + 'v),
column: Column<Fixed>,
offset: usize,
_to: &'v mut (dyn FnMut() -> Value<Rational<F>> + 'v),
) -> Result<Cell, Error> {
self.columns.insert(Column::<Any>::from(column).into());
self.row_count = cmp::max(self.row_count, offset + 1);
Ok(Cell {
region_index: self.region_index,
row_offset: offset,
column: column.into(),
})
}
fn name_column<'v>(
&'v mut self,
_annotation: &'v (dyn Fn() -> String + 'v),
_column: Column<Any>,
) {
}
fn constrain_constant(&mut self, _cell: Cell, _constant: Rational<F>) -> Result<(), Error> {
Ok(())
}
fn constrain_equal(&mut self, _left: Cell, _right: Cell) -> Result<(), Error> {
Ok(())
}
}