use std::{
any::Any,
io,
path::{Path, PathBuf},
};
use cairo_vm::{
cairo_run::CairoRunConfig,
types::{
errors::program_errors::ProgramError, layout::CairoLayoutParams, layout_name::LayoutName,
program::Program,
},
vm::runners::cairo_runner::CairoRunner,
Felt252,
};
use crate::types::RunMode;
#[derive(Debug)]
pub enum ProgramInput {
Path(PathBuf),
Json(String),
Value(Box<dyn Any>),
}
impl ProgramInput {
pub fn from_value<T: Any>(value: T) -> Self {
Self::Value(Box::new(value))
}
}
pub fn get_program(program: &Path) -> Result<Program, ProgramError> {
Program::from_file(program, Some("main"))
}
pub fn get_program_input_from_path(
program_input: &Option<PathBuf>,
) -> io::Result<Option<ProgramInput>> {
Ok(program_input
.as_ref()
.map(|input_path| ProgramInput::Path(input_path.to_path_buf())))
}
pub fn get_cairo_run_config(
dynamic_params_file: &Option<PathBuf>,
layout: LayoutName,
proof_mode: bool,
disable_trace_padding: bool,
allow_missing_builtins: bool,
relocate_mem: bool,
) -> std::io::Result<CairoRunConfig<'static>> {
let dynamic_layout_params = match dynamic_params_file {
Some(file) => {
assert!(
layout == LayoutName::dynamic,
"dynamic_params_file should not be provided for layout {layout}."
);
Some(CairoLayoutParams::from_file(file)?)
}
None => None,
};
Ok(if proof_mode {
RunMode::Proof {
layout,
dynamic_layout_params,
disable_trace_padding,
relocate_mem,
}
.create_config()
} else {
RunMode::Validation {
layout,
allow_missing_builtins,
}
.create_config()
})
}
pub fn write_output_to_file(runner: &mut CairoRunner, output_path: PathBuf) -> anyhow::Result<()> {
let mut output_buffer = String::new();
runner.vm.write_output(&mut output_buffer)?;
let output_lines = output_buffer
.lines()
.map(|line| {
Felt252::from_dec_str(line)
.map_err(|_| anyhow::anyhow!("Failed to parse output line as Felt decimal: {line}"))
})
.collect::<Result<Vec<Felt252>, anyhow::Error>>()?;
std::fs::write(&output_path, sonic_rs::to_string_pretty(&output_lines)?)?;
Ok(())
}