use core::convert::Infallible;
use crate::error::{
FallibleTraceSnapshotRunError, RunError, TraceSnapshotError, TraceSnapshotRunError,
TracedRunError,
};
use crate::runtime::RuntimeInput;
use crate::trace::{BorrowedTraceEvent, TraceSnapshotEvent};
use super::Program;
use super::limits::{RunLimits, TraceSnapshotLimits};
use super::result::RunResult;
enum SnapshotTraceCallbackError<E> {
Snapshot(TraceSnapshotError),
Trace(E),
}
impl Program {
pub fn run_with_trace_snapshots<'program, F>(
&'program self,
input: RuntimeInput<'_>,
limits: TraceSnapshotLimits,
mut trace: F,
) -> Result<RunResult, TraceSnapshotRunError>
where
F: FnMut(TraceSnapshotEvent<'program>),
{
match self.try_run_with_trace_snapshots(input, limits, |event| {
trace(event);
Ok::<(), Infallible>(())
}) {
Ok(result) => Ok(result),
Err(FallibleTraceSnapshotRunError::Run(error)) => {
Err(TraceSnapshotRunError::Run(error))
}
Err(FallibleTraceSnapshotRunError::Snapshot(error)) => {
Err(TraceSnapshotRunError::Snapshot(error))
}
Err(FallibleTraceSnapshotRunError::Trace(error)) => match error {},
}
}
pub fn try_run_with_trace_snapshots<'program, F, E>(
&'program self,
input: RuntimeInput<'_>,
limits: TraceSnapshotLimits,
mut trace: F,
) -> Result<RunResult, FallibleTraceSnapshotRunError<E>>
where
F: FnMut(TraceSnapshotEvent<'program>) -> Result<(), E>,
{
let result = self.try_run_with_borrowed_trace(input, limits.run_limits(), |event| {
let snapshot = event
.to_snapshot(limits.snapshot_byte_limit())
.map_err(SnapshotTraceCallbackError::Snapshot)?;
trace(snapshot).map_err(SnapshotTraceCallbackError::Trace)
});
match result {
Ok(result) => Ok(result),
Err(TracedRunError::Run(error)) => Err(FallibleTraceSnapshotRunError::Run(error)),
Err(TracedRunError::Trace(SnapshotTraceCallbackError::Snapshot(error))) => {
Err(FallibleTraceSnapshotRunError::Snapshot(error))
}
Err(TracedRunError::Trace(SnapshotTraceCallbackError::Trace(error))) => {
Err(FallibleTraceSnapshotRunError::Trace(error))
}
}
}
pub fn run_with_borrowed_trace<'program, F>(
&'program self,
input: RuntimeInput<'_>,
limits: RunLimits,
mut trace: F,
) -> Result<RunResult, RunError>
where
F: for<'run> FnMut(BorrowedTraceEvent<'program, 'run>),
{
match self.try_run_with_borrowed_trace(input, limits, |event| {
trace(event);
Ok::<(), Infallible>(())
}) {
Ok(result) => Ok(result),
Err(TracedRunError::Run(error)) => Err(error),
Err(TracedRunError::Trace(error)) => match error {},
}
}
pub fn try_run_with_borrowed_trace<'program, F, E>(
&'program self,
input: RuntimeInput<'_>,
limits: RunLimits,
trace: F,
) -> Result<RunResult, TracedRunError<E>>
where
F: for<'run> FnMut(BorrowedTraceEvent<'program, 'run>) -> Result<(), E>,
{
crate::runtime::Execution::new(self, input, limits)
.map_err(TracedRunError::Run)?
.run_with_borrowed_trace(trace)
}
}