use std::collections::BTreeMap;
use std::ops::Deref;
use std::sync::Arc;
use std::time::Duration;
use crate::Result;
use zisk_common::ProofKind;
use zisk_prover_backend::{GuestProgram, ProveOutput};
use crate::hints::HintsSource;
use crate::input_source::InputSource;
use crate::job_handle::{subscriber_list_from, JobHandle, JobId, Subscriber, SubscriberList};
use crate::{Client, ClientSync, ExecutorKind, RemoteClient};
pub struct ProveResult {
pub(crate) job_id: Option<JobId>,
output: ProveOutput,
}
impl ProveResult {
pub fn new(output: ProveOutput, job_id: Option<JobId>) -> Self {
Self { output, job_id }
}
pub fn job_id(&self) -> Option<&JobId> {
self.job_id.as_ref()
}
}
impl Deref for ProveResult {
type Target = ProveOutput;
fn deref(&self) -> &Self::Target {
&self.output
}
}
impl From<ProveOutput> for ProveResult {
fn from(output: ProveOutput) -> Self {
Self { output, job_id: None }
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum JobEvent {
All,
Started,
Progress(u8),
Completed,
Failed(String),
}
pub struct ProveRequest<'a, C> {
client: &'a C,
program: &'a GuestProgram,
stdin: InputSource,
hints: Option<HintsSource>,
executor: ExecutorKind,
timeout: Option<Duration>,
proof_kind: ProofKind,
subscribers: Vec<Subscriber>,
}
#[allow(private_bounds)]
impl<'a, C: Client> ProveRequest<'a, C> {
pub(crate) fn new(
client: &'a C,
program: &'a GuestProgram,
stdin: impl Into<InputSource>,
executor: ExecutorKind,
) -> Self {
Self {
client,
program,
stdin: stdin.into(),
hints: None,
executor,
timeout: None,
proof_kind: ProofKind::default(),
subscribers: Vec::new(),
}
}
#[must_use]
pub fn hints(mut self, hints: impl Into<HintsSource>) -> Self {
self.hints = Some(hints.into());
self
}
#[must_use]
pub fn executor(mut self, executor: ExecutorKind) -> Self {
self.executor = executor;
self
}
#[must_use]
pub fn timeout(mut self, duration: Duration) -> Self {
self.timeout = Some(duration);
self
}
#[must_use]
pub fn wrap(mut self, kind: ProofKind) -> Self {
self.proof_kind = kind;
self
}
#[must_use]
pub fn on(mut self, event: JobEvent, cb: impl Fn(JobEvent) + Send + Sync + 'static) -> Self {
self.subscribers.push((event, Arc::new(cb)));
self
}
pub fn run(self) -> Result<JobHandle<ProveResult>> {
let subs: SubscriberList = subscriber_list_from(self.subscribers);
self.client.run_prove(
self.program,
self.stdin,
self.hints,
self.executor,
self.proof_kind,
self.timeout,
subs,
)
}
}
#[allow(private_bounds)]
impl<'a, C: ClientSync> ProveRequest<'a, C> {
pub fn run_sync(self) -> Result<ProveResult> {
let subs = subscriber_list_from(self.subscribers);
self.client.run_prove_sync(
self.program,
self.stdin,
self.hints,
self.executor,
self.proof_kind,
subs,
)
}
}
pub struct ProveRequestExt<'a> {
client: &'a RemoteClient,
program: &'a GuestProgram,
stdin: InputSource,
hints: Option<HintsSource>,
executor: ExecutorKind,
timeout: Option<Duration>,
proof_kind: ProofKind,
subscribers: Vec<Subscriber>,
metadata: BTreeMap<String, String>,
}
impl<'a> ProveRequestExt<'a> {
pub(crate) fn new(
client: &'a RemoteClient,
program: &'a GuestProgram,
stdin: impl Into<InputSource>,
) -> Self {
Self {
client,
program,
stdin: stdin.into(),
hints: None,
executor: ExecutorKind::default(),
timeout: None,
proof_kind: ProofKind::default(),
subscribers: Vec::new(),
metadata: BTreeMap::new(),
}
}
#[must_use]
pub fn metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.metadata.insert(key.into(), value.into());
self
}
#[must_use]
pub fn hints(mut self, hints: impl Into<HintsSource>) -> Self {
self.hints = Some(hints.into());
self
}
#[must_use]
pub fn executor(mut self, executor: ExecutorKind) -> Self {
self.executor = executor;
self
}
#[must_use]
pub fn timeout(mut self, duration: Duration) -> Self {
self.timeout = Some(duration);
self
}
#[must_use]
pub fn wrap(mut self, kind: ProofKind) -> Self {
self.proof_kind = kind;
self
}
#[must_use]
pub fn on(mut self, event: JobEvent, cb: impl Fn(JobEvent) + Send + Sync + 'static) -> Self {
self.subscribers.push((event, Arc::new(cb)));
self
}
pub fn run(self) -> Result<JobHandle<ProveResult>> {
let subs: SubscriberList = subscriber_list_from(self.subscribers);
self.client.do_prove_ext(
self.program,
self.stdin,
self.hints,
self.executor,
self.proof_kind,
self.timeout,
subs,
self.metadata,
)
}
}