use core::fmt::Debug;
use midnight_proofs::circuit::Value;
#[cfg(any(test, feature = "testing"))]
use rand::RngCore;
use crate::{field::AssignedNative, CircuitField};
pub trait Instantiable<F: CircuitField>: InnerValue {
fn as_public_input(element: &<Self as InnerValue>::Element) -> Vec<F>;
}
pub trait InnerValue: Clone + Debug {
type Element: Clone + Debug;
fn value(&self) -> Value<Self::Element>;
}
impl<T: InnerValue, const L: usize> InnerValue for [T; L] {
type Element = [T::Element; L];
fn value(&self) -> Value<Self::Element> {
let val = Value::from_iter(self.iter().map(|val| val.value()));
val.map(|v: Vec<T::Element>| v.try_into().unwrap())
}
}
pub trait InnerConstants: InnerValue {
fn inner_zero() -> Self::Element;
fn inner_one() -> Self::Element;
}
impl<F: CircuitField> Instantiable<F> for AssignedNative<F> {
fn as_public_input(element: &F) -> Vec<F> {
vec![*element]
}
}
impl<F: CircuitField> InnerValue for AssignedNative<F> {
type Element = F;
fn value(&self) -> Value<F> {
self.value().cloned()
}
}
impl<F: CircuitField> InnerConstants for AssignedNative<F> {
fn inner_zero() -> F {
F::ZERO
}
fn inner_one() -> F {
F::ONE
}
}
#[cfg(any(test, feature = "testing"))]
pub trait Invertible {
fn invert(&self) -> Self;
}
#[cfg(any(test, feature = "testing"))]
impl<F: CircuitField> Invertible for F {
fn invert(&self) -> F {
self.invert().unwrap()
}
}
#[cfg(any(test, feature = "testing"))]
pub trait Sampleable: InnerValue {
fn sample_inner(rng: impl RngCore) -> Self::Element;
}
#[cfg(any(test, feature = "testing"))]
impl<F: CircuitField> Sampleable for AssignedNative<F> {
fn sample_inner(rng: impl RngCore) -> F {
F::random(rng)
}
}