use std::ops::Deref;
use ff::Field;
use thiserror::Error;
use crate::{
expressions::ExprBuilder,
info_traits::CreateQuery,
query::{Advice, Fixed, Instance},
};
pub trait ColumnType: std::fmt::Debug + Copy + Clone + PartialEq + Eq + std::hash::Hash {
fn query_cell<F: Field, E: ExprBuilder<F>>(&self, index: usize, at: Rotation) -> E;
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub enum Any {
Fixed,
Advice,
Instance,
}
impl std::fmt::Debug for Any {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Fixed => write!(f, "Fix"),
Self::Advice => write!(f, "Adv"),
Self::Instance => write!(f, "Ins"),
}
}
}
impl ColumnType for Any {
fn query_cell<F: Field, E: ExprBuilder<F>>(&self, index: usize, at: Rotation) -> E {
match self {
Any::Fixed => Fixed.query_cell(index, at),
Any::Advice => Advice.query_cell(index, at),
Any::Instance => Instance.query_cell(index, at),
}
}
}
impl ColumnType for Fixed {
fn query_cell<F: Field, E: ExprBuilder<F>>(&self, index: usize, at: Rotation) -> E {
E::FixedQuery::query_expr(index, at)
}
}
impl ColumnType for Advice {
fn query_cell<F: Field, E: ExprBuilder<F>>(&self, index: usize, at: Rotation) -> E {
E::AdviceQuery::query_expr(index, at)
}
}
impl ColumnType for Instance {
fn query_cell<F: Field, E: ExprBuilder<F>>(&self, index: usize, at: Rotation) -> E {
E::InstanceQuery::query_expr(index, at)
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Column<C: ColumnType> {
index: usize,
column_type: C,
}
impl<C: ColumnType + std::fmt::Debug> std::fmt::Debug for Column<C> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}:{}", self.column_type, self.index)
}
}
impl<C: ColumnType> Column<C> {
pub fn new(index: usize, column_type: C) -> Self {
Self { index, column_type }
}
pub fn index(&self) -> usize {
self.index
}
pub fn column_type(&self) -> &C {
&self.column_type
}
pub fn query_cell<F: Field, E: ExprBuilder<F>>(&self, at: Rotation) -> E {
self.column_type.query_cell(self.index, at)
}
}
impl From<Column<Fixed>> for Column<Any> {
fn from(value: Column<Fixed>) -> Self {
Self {
index: value.index,
column_type: Any::Fixed,
}
}
}
impl TryFrom<Column<Any>> for Column<Fixed> {
type Error = TableError;
fn try_from(value: Column<Any>) -> Result<Self, Self::Error> {
match value.column_type {
Any::Fixed => Ok(Self {
index: value.index,
column_type: Fixed,
}),
c => Err(TableError::ExpectedFixed(c)),
}
}
}
impl From<Column<Advice>> for Column<Any> {
fn from(value: Column<Advice>) -> Self {
Self {
index: value.index,
column_type: Any::Advice,
}
}
}
impl TryFrom<Column<Any>> for Column<Advice> {
type Error = TableError;
fn try_from(value: Column<Any>) -> Result<Self, Self::Error> {
match value.column_type {
Any::Advice => Ok(Self {
index: value.index,
column_type: Advice,
}),
c => Err(TableError::ExpectedAdvice(c)),
}
}
}
impl From<Column<Instance>> for Column<Any> {
fn from(value: Column<Instance>) -> Self {
Self {
index: value.index,
column_type: Any::Instance,
}
}
}
impl TryFrom<Column<Any>> for Column<Instance> {
type Error = TableError;
fn try_from(value: Column<Any>) -> Result<Self, Self::Error> {
match value.column_type {
Any::Instance => Ok(Self {
index: value.index,
column_type: Instance,
}),
c => Err(TableError::ExpectedInstance(c)),
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
pub struct Cell {
pub region_index: RegionIndex,
pub row_offset: usize,
pub column: Column<Any>,
}
pub type Rotation = i32;
pub trait RotationExt {
fn cur() -> Self;
fn next() -> Self;
fn prev() -> Self;
}
impl RotationExt for Rotation {
fn cur() -> Self {
0
}
fn next() -> Self {
1
}
fn prev() -> Self {
-1
}
}
#[derive(Eq, Hash, PartialEq, Debug, Copy, Clone)]
pub struct RegionIndex(usize);
impl Deref for RegionIndex {
type Target = usize;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<usize> for RegionIndex {
fn from(value: usize) -> Self {
Self(value)
}
}
#[derive(Eq, Hash, PartialEq, Debug, Copy, Clone)]
pub struct RegionStart(usize);
impl Deref for RegionStart {
type Target = usize;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<usize> for RegionStart {
fn from(value: usize) -> Self {
Self(value)
}
}
#[derive(Error, Copy, Clone, Debug)]
pub enum TableError {
#[error("Expected Any::Fixed. Got {0:?}")]
ExpectedFixed(Any),
#[error("Expected Any::Advice. Got {0:?}")]
ExpectedAdvice(Any),
#[error("Expected Any::Instance. Got {0:?}")]
ExpectedInstance(Any),
}