Skip to main content

cargo_airbender/
input.rs

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}