Skip to main content

inspect_response/
inspect_response.rs

1//! Inspect local ICP CLI output without running a command or printing its payload.
2
3use ic_host_tools::{
4    artifact::{hash_reader, read_file},
5    response::{ResponseFormat, ResponseLimits, decode},
6};
7use std::{error::Error, io, path::Path};
8
9fn main() -> Result<(), Box<dyn Error>> {
10    let mut args = std::env::args_os().skip(1);
11    let path = args.next().ok_or_else(|| {
12        invalid_argument(
13            "usage: inspect_response PATH json|hex|labeled MAX_INPUT_BYTES MAX_DECODED_BYTES",
14        )
15    })?;
16    let format = match args.next().as_deref().and_then(std::ffi::OsStr::to_str) {
17        Some("json") => ResponseFormat::Json,
18        Some("hex") => ResponseFormat::Hex,
19        Some("labeled") => ResponseFormat::LabeledHex,
20        _ => return Err(invalid_argument("format must be json, hex or labeled").into()),
21    };
22    let mut limit = || -> Result<usize, Box<dyn Error>> {
23        Ok(args
24            .next()
25            .ok_or_else(|| invalid_argument("missing response limit"))?
26            .to_str()
27            .ok_or_else(|| invalid_argument("limits must be UTF-8"))?
28            .parse()?)
29    };
30    let limits = ResponseLimits {
31        input_bytes: limit()?,
32        decoded_bytes: limit()?,
33    };
34    if args.next().is_some() {
35        return Err(invalid_argument("unexpected argument").into());
36    }
37    let input = read_file(Path::new(&path), limits.input_bytes)?;
38    let bytes = decode(&input, format, limits)?;
39    let identity = hash_reader(bytes.as_slice(), u64::try_from(limits.decoded_bytes)?)?;
40    println!(
41        "response_bytes={} sha256={}",
42        identity.bytes, identity.sha256
43    );
44    Ok(())
45}
46
47fn invalid_argument(message: &'static str) -> io::Error {
48    io::Error::new(io::ErrorKind::InvalidInput, message)
49}