use std::ops::Range;
use midnight_proofs::circuit::Value;
use crate::{
field::AssignedNative,
types::{AssignedByte, InnerValue},
CircuitField,
};
#[derive(Clone, Debug)]
pub struct AssignedVector<F: CircuitField, T: Vectorizable, const M: usize, const A: usize> {
pub(crate) buffer: Box<[T; M]>,
pub(crate) len: AssignedNative<F>,
}
pub fn get_lims<const M: usize, const A: usize>(len: usize) -> Range<usize> {
let final_pad_len = (A - (len % A)) % A;
M - len - final_pad_len..M - final_pad_len
}
impl<F: CircuitField, const M: usize, T: Vectorizable, const A: usize> InnerValue
for AssignedVector<F, T, M, A>
{
type Element = Vec<T::Element>;
fn value(&self) -> Value<Self::Element> {
let data = Value::<Vec<T::Element>>::from_iter(self.buffer.iter().map(|v| v.value()));
let idxs: Value<_> = self.len.value().map(|len| {
let len: usize = len.to_biguint().try_into().unwrap();
let end_pad = (A - (len % A)) % A;
(M - len - end_pad, M - end_pad)
});
data.zip(idxs).map(|(data, idxs)| data[idxs.0..idxs.1].to_vec())
}
}
pub trait Vectorizable: InnerValue {
const FILLER: Self::Element;
}
impl<F: CircuitField> Vectorizable for AssignedNative<F> {
const FILLER: F = F::ZERO;
}
impl<F: CircuitField> Vectorizable for AssignedByte<F> {
const FILLER: u8 = 0u8;
}