use std::fmt::Debug;
use futures::future::BoxFuture;
use crate::{correlated_randomness::CorrelatedBatch, utils::TryFuture};
pub trait CorrelationGenerator<PB: CorrelatedBatch>: Send {
type Net: Send;
type Error: Debug + Clone + Send;
const SUPPORTS_UNILATERAL_SKIP: bool = false;
fn run(&mut self, net: &mut Self::Net) -> impl TryFuture<Ok = PB, Error = Self::Error>;
fn skip(
&mut self,
_n_elements: usize,
_net: &mut Self::Net,
) -> impl TryFuture<Ok = (), Error = Self::Error> {
async move {
unreachable!(
"skip() called on a generator without SUPPORTS_UNILATERAL_SKIP; the stream \
dispatcher must guard on the const before ever calling skip()"
)
}
}
fn run_for(
&mut self,
n_elements: usize,
net: &mut Self::Net,
) -> impl TryFuture<Ok = Vec<PB::Item>, Error = Self::Error> {
let n_batches = n_elements.div_ceil(PB::batch_size());
let mut result = Vec::with_capacity(n_batches * PB::batch_size());
async move {
for _ in 0..n_batches {
let batch = self.run(net).await?;
result.extend(batch.into_iter());
}
Ok(result)
}
}
}
pub trait PipelinedCorrelationGenerator<PB: CorrelatedBatch>: CorrelationGenerator<PB> {
fn issue_for(
&mut self,
n_elements: usize,
net: &mut Self::Net,
) -> BoxFuture<'static, Result<Vec<PB::Item>, Self::Error>>;
}