Skip to main content

airbender_host/runner/
mod.rs

1use crate::cycle_marker::CycleMarker;
2use crate::error::{HostError, Result};
3use crate::receipt::Receipt;
4use std::path::PathBuf;
5
6mod transpiler_runner;
7
8pub use self::transpiler_runner::{TranspilerRunner, TranspilerRunnerBuilder};
9
10/// Flamegraph collection options for execution runners.
11#[derive(Clone, Debug)]
12pub struct FlamegraphConfig {
13    pub output: PathBuf,
14    pub sampling_rate: usize,
15    pub inverse: bool,
16    pub elf_path: Option<PathBuf>,
17}
18
19pub const DEFAULT_CYCLES: usize = 90_000_000_000;
20
21/// Host runner interface.
22pub trait Runner {
23    fn run(&self, input_words: &[u32]) -> Result<ExecutionResult>;
24}
25
26/// Execution outcome for transpiler based runners.
27#[derive(Debug)]
28pub struct ExecutionResult {
29    pub receipt: Receipt,
30    pub cycles_executed: usize,
31    pub reached_end: bool,
32    pub cycle_markers: Option<CycleMarker>,
33}
34
35/// Resolve the cycle budget from an explicit override or default.
36pub fn resolve_cycles(explicit_cycles: Option<usize>) -> Result<usize> {
37    let cycles = explicit_cycles.unwrap_or(DEFAULT_CYCLES);
38    if cycles == 0 {
39        return Err(HostError::Runner(
40            "cycle budget must be greater than zero".to_string(),
41        ));
42    }
43    Ok(cycles)
44}
45
46#[cfg(test)]
47mod tests {
48    use super::{resolve_cycles, DEFAULT_CYCLES};
49
50    #[test]
51    fn resolve_cycles_uses_explicit_value() {
52        assert_eq!(resolve_cycles(Some(100)).expect("cycles"), 100);
53    }
54
55    #[test]
56    fn resolve_cycles_uses_default_when_unspecified() {
57        assert_eq!(resolve_cycles(None).expect("cycles"), DEFAULT_CYCLES);
58    }
59
60    #[test]
61    fn resolve_cycles_rejects_zero() {
62        let err = resolve_cycles(Some(0)).expect_err("error");
63        assert_eq!(
64            err.to_string(),
65            "runner error: cycle budget must be greater than zero"
66        );
67    }
68}