1use crate::error::{CliError, Result};
2use std::fs;
3use std::path::Path;
4
5pub fn parse_input_words(path: &Path) -> Result<Vec<u32>> {
6 let raw = fs::read_to_string(path).map_err(|err| match err.kind() {
7 std::io::ErrorKind::NotFound => CliError::with_source(
8 format!("input file `{}` does not exist", path.display()),
9 err,
10 )
11 .with_hint("provide an existing hex file with `--input <path>`"),
12 _ => CliError::with_source(
13 format!("failed to read input file `{}`", path.display()),
14 err,
15 ),
16 })?;
17
18 let mut hex: String = raw
19 .chars()
20 .filter(|character| !character.is_whitespace())
21 .collect();
22 if let Some(stripped) = hex.strip_prefix("0x") {
23 hex = stripped.to_string();
24 }
25
26 if hex.is_empty() {
27 return Ok(Vec::new());
28 }
29
30 if !hex.len().is_multiple_of(8) {
31 return Err(CliError::new(format!(
32 "input hex length must be a multiple of 8 (got {})",
33 hex.len()
34 ))
35 .with_hint("encode each u32 word as exactly 8 hexadecimal characters"));
36 }
37
38 let mut words = Vec::with_capacity(hex.len() / 8);
39 for chunk in hex.as_bytes().chunks(8) {
40 let chunk_str = std::str::from_utf8(chunk)
41 .map_err(|err| CliError::with_source("failed to parse input as UTF-8", err))?;
42 let word = u32::from_str_radix(chunk_str, 16).map_err(|err| {
43 CliError::with_source(format!("failed to parse hex word `{chunk_str}`"), err)
44 .with_hint("input must contain hexadecimal characters only")
45 })?;
46 words.push(word);
47 }
48
49 Ok(words)
50}