use std::cmp;
use std::collections::HashSet;
use std::fmt;
use ff::Field;
use super::{Cell, RegionIndex};
use crate::plonk::{Advice, Any, Assigned, Column, Error, Fixed, Instance, Selector, TableColumn};
pub trait RegionLayouter<F: Field>: fmt::Debug {
fn enable_selector<'v>(
&'v mut self,
annotation: &'v (dyn Fn() -> String + 'v),
selector: &Selector,
offset: usize,
) -> Result<(), Error>;
fn assign_advice<'v>(
&'v mut self,
annotation: &'v (dyn Fn() -> String + 'v),
column: Column<Advice>,
offset: usize,
to: &'v mut (dyn FnMut() -> Result<Assigned<F>, Error> + '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: Assigned<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, Option<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() -> Result<Assigned<F>, Error> + 'v),
) -> Result<Cell, Error>;
fn constrain_constant(&mut self, cell: Cell, constant: Assigned<F>) -> Result<(), Error>;
fn constrain_equal(&mut self, left: Cell, right: Cell) -> Result<(), Error>;
}
pub trait TableLayouter<F: Field>: fmt::Debug {
fn assign_cell<'v>(
&'v mut self,
annotation: &'v (dyn Fn() -> String + 'v),
column: TableColumn,
offset: usize,
to: &'v mut (dyn FnMut() -> Result<Assigned<F>, Error> + 'v),
) -> 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() -> Result<Assigned<F>, Error> + '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: Assigned<F>,
) -> Result<Cell, Error> {
self.assign_advice(annotation, column, offset, &mut || Ok(constant))
}
fn assign_advice_from_instance<'v>(
&mut self,
_: &'v (dyn Fn() -> String + 'v),
_: Column<Instance>,
_: usize,
advice: Column<Advice>,
offset: usize,
) -> Result<(Cell, Option<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(),
},
None,
))
}
fn assign_fixed<'v>(
&'v mut self,
_: &'v (dyn Fn() -> String + 'v),
column: Column<Fixed>,
offset: usize,
_to: &'v mut (dyn FnMut() -> Result<Assigned<F>, Error> + '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 constrain_constant(&mut self, _cell: Cell, _constant: Assigned<F>) -> Result<(), Error> {
Ok(())
}
fn constrain_equal(&mut self, _left: Cell, _right: Cell) -> Result<(), Error> {
Ok(())
}
}