use std::io;
use crate::{AtomicConfig, Config, Context, ContextUnit, Element, Preamble, Scalar};
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct IndexedWitness {
index: usize,
origin: Option<usize>,
value: Scalar,
}
impl IndexedWitness {
pub const fn new(index: usize, origin: Option<usize>, value: Scalar) -> Self {
Self {
index,
origin,
value,
}
}
pub const fn index(&self) -> usize {
self.index
}
pub const fn origin(&self) -> &Option<usize> {
&self.origin
}
pub const fn value(&self) -> &Scalar {
&self.value
}
}
impl Element for IndexedWitness {
type Config = Config;
fn zeroed() -> Self {
Self::default()
}
fn len(config: &Self::Config) -> usize {
usize::len(&AtomicConfig) + <Option<usize>>::len(&AtomicConfig) + Scalar::len(config)
}
fn to_buffer(&self, config: &Self::Config, context: &mut ContextUnit, buf: &mut [u8]) {
let buf = self.index.encode(&AtomicConfig, context, buf);
let buf = self.origin.encode(&AtomicConfig, context, buf);
let _ = self.value.encode(config, context, buf);
}
fn try_from_buffer_in_place<S>(
&mut self,
config: &Self::Config,
context: &mut Context<S>,
buf: &[u8],
) -> io::Result<()>
where
S: io::Read + io::Seek,
{
Self::validate_buffer_len(config, buf.len())?;
let buf = self
.index
.try_decode_in_place(&AtomicConfig, context, buf)?;
let buf = self
.origin
.try_decode_in_place(&AtomicConfig, context, buf)?;
let _ = self.value.try_decode_in_place(config, context, buf)?;
Ok(())
}
fn validate(&self, preamble: &Preamble) -> io::Result<()> {
self.index.validate(preamble)?;
self.origin.map(|o| o.validate(preamble)).transpose()?;
self.value.validate(preamble)?;
if self.index >= preamble.witnesses {
return Err(io::Error::new(
io::ErrorKind::Other,
"the provided witness index does not correspond to a valid allocated witness",
));
}
if let Some(o) = self.origin {
if o >= preamble.constraints {
return Err(io::Error::new(
io::ErrorKind::Other,
"the provided constraint index does not correspond to a valid gate",
));
}
}
Ok(())
}
}