cargo_openvm/
util.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use std::{
    fmt::Display,
    fs::{read, read_to_string},
    path::{Path, PathBuf},
    str::FromStr,
};

use eyre::Result;
use openvm_sdk::{
    config::{AppConfig, SdkVmConfig},
    StdIn,
};
use serde::de::DeserializeOwned;

use crate::default::default_app_config;

#[allow(dead_code)]
#[derive(Debug, Clone)]
pub(crate) enum Input {
    FilePath(PathBuf),
    HexBytes(Vec<u8>),
}

impl FromStr for Input {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if is_valid_hex_string(s) {
            // Remove 0x prefix if present
            let s = if s.starts_with("0x") {
                s.strip_prefix("0x").unwrap()
            } else {
                s
            };
            if s.is_empty() {
                return Ok(Input::HexBytes(Vec::new()));
            }
            if !s.chars().all(|c| c.is_ascii_hexdigit()) {
                return Err("Invalid hex string.".to_string());
            }
            let bytes = hex::decode(s).map_err(|e| e.to_string())?;
            Ok(Input::HexBytes(bytes))
        } else if PathBuf::from(s).exists() {
            Ok(Input::FilePath(PathBuf::from(s)))
        } else {
            Err("Input must be a valid file path or hex string.".to_string())
        }
    }
}

pub(crate) fn is_valid_hex_string(s: &str) -> bool {
    if s.len() % 2 != 0 {
        return false;
    }
    // All hex digits with optional 0x prefix
    s.starts_with("0x") && s[2..].chars().all(|c| c.is_ascii_hexdigit())
        || s.chars().all(|c| c.is_ascii_hexdigit())
}

pub(crate) fn write_status(style: &dyn Display, status: &str, msg: &str) {
    println!("{style}{status:>12}{style:#} {msg}");
}

pub(crate) fn classical_exe_path(elf_path: &Path) -> PathBuf {
    elf_path.with_extension("vmexe")
}

pub(crate) fn read_to_struct_toml<T: DeserializeOwned>(path: &PathBuf) -> Result<T> {
    let toml = read_to_string(path.as_ref() as &Path)?;
    let ret = toml::from_str(&toml)?;
    Ok(ret)
}

pub(crate) fn read_to_stdin(input: &Option<Input>) -> Result<StdIn> {
    match input {
        Some(Input::FilePath(path)) => {
            let bytes = read(path)?;
            Ok(StdIn::from_bytes(&bytes))
        }
        Some(Input::HexBytes(bytes)) => Ok(StdIn::from_bytes(bytes)),
        None => Ok(StdIn::default()),
    }
}

pub(crate) fn read_config_toml_or_default(config: &PathBuf) -> Result<AppConfig<SdkVmConfig>> {
    if config.exists() {
        read_to_struct_toml(config)
    } else {
        println!(
            "{:?} not found, using default application configuration",
            config
        );
        Ok(default_app_config())
    }
}