cairo_program_runner_lib/
tasks.rs1use std::{
2 path::{Path, PathBuf},
3 str::FromStr,
4};
5
6use cairo_lang_executable::executable::EntryPointKind;
7use cairo_lang_executable::executable::Executable;
8use cairo_lang_execute_utils::{program_and_hints_from_executable, user_args_from_flags};
9use cairo_vm::types::errors::program_errors::ProgramError;
10use cairo_vm::types::program::Program;
11use cairo_vm::vm::runners::cairo_pie::CairoPie;
12use num_bigint::BigInt;
13use serde_json::Value;
14
15use crate::{types::Cairo1Executable, Cairo0Executable, Task};
16
17#[derive(thiserror::Error, Debug)]
18pub enum BootloaderTaskError {
19 #[error("Failed to read program: {0}")]
20 Program(#[from] ProgramError),
21
22 #[error("Failed to read PIE: {0}")]
23 Pie(#[from] std::io::Error),
24
25 #[error("Cairo1 error: {0}")]
26 Cairo1(String),
27}
28
29pub fn create_cairo0_program_task(
39 program_path: &Path,
40 program_input: Option<String>,
41) -> Result<Task, BootloaderTaskError> {
42 let program =
43 Program::from_file(program_path, Some("main")).map_err(BootloaderTaskError::Program)?;
44 Ok(Task::Cairo0Program(Cairo0Executable {
45 program,
46 program_input,
47 }))
48}
49
50pub fn create_pie_task(pie_path: &Path) -> Result<Task, BootloaderTaskError> {
60 let pie = CairoPie::read_zip_file(pie_path).map_err(BootloaderTaskError::Pie)?;
61 Ok(Task::Pie(pie))
62}
63
64pub fn create_cairo1_program_task(
65 path: &PathBuf,
66 user_args_list: Option<Vec<Value>>,
67 user_args_file: Option<PathBuf>,
68) -> Result<Task, BootloaderTaskError> {
69 let file = std::fs::File::open(path)
70 .map_err(|e| BootloaderTaskError::Cairo1(format!("Failed to open file: {e:?}")))?;
71 let executable: Executable = serde_json::from_reader(file).map_err(|e| {
72 BootloaderTaskError::Cairo1(format!("Failed reading prebuilt executable: {e:?}"))
73 })?;
74 let user_args_list: Vec<BigInt> = user_args_list
75 .unwrap_or_default()
76 .iter()
77 .map(|n| BigInt::from_str(&n.to_string()).unwrap())
78 .collect();
79
80 let entrypoint = executable
81 .entrypoints
82 .iter()
83 .find(|e| matches!(e.kind, EntryPointKind::Bootloader))
84 .ok_or_else(|| {
85 BootloaderTaskError::Cairo1(format!(
86 "{:?} entrypoint not found",
87 EntryPointKind::Bootloader
88 ))
89 })?;
90 let (program, string_to_hint) = program_and_hints_from_executable(&executable, entrypoint)
91 .map_err(|e| BootloaderTaskError::Cairo1(format!("Failed to parse executable: {e:?}")))?;
92 let user_args = user_args_from_flags(user_args_file.as_ref(), &user_args_list)
93 .map_err(|e| BootloaderTaskError::Cairo1(format!("Failed to parse user args: {e:?}")))?;
94 Ok(Task::Cairo1Program(Cairo1Executable {
95 program,
96 user_args,
97 string_to_hint,
98 }))
99}