Skip to main content

ic_query/
lib.rs

1mod cache_file;
2mod cli;
3mod duration;
4mod hex;
5mod ic_registry;
6mod nns;
7mod output;
8mod progress;
9mod project;
10mod runtime;
11pub(crate) mod snapshot_cache;
12mod sns;
13pub mod subnet_catalog;
14mod table;
15mod token_amount;
16
17#[cfg(test)]
18mod test_support;
19
20use crate::cli::{
21    clap::{parse_matches_or_usage, string_option},
22    globals::{
23        DISPATCH_ARGS, apply_global_network, command_local_global_option,
24        top_level_dispatch_command,
25    },
26    help::{first_arg_is_help, usage},
27};
28use std::ffi::OsString;
29use thiserror::Error as ThisError;
30
31const VERSION_TEXT: &str = concat!("icq ", env!("CARGO_PKG_VERSION"));
32
33///
34/// IcQueryError
35///
36#[derive(Debug, ThisError)]
37pub enum IcQueryError {
38    #[error("{0}")]
39    Usage(String),
40
41    #[error("nns: {0}")]
42    Nns(String),
43
44    #[error("sns: {0}")]
45    Sns(String),
46}
47
48/// Run the CLI from process arguments.
49pub fn run_from_env() -> Result<(), IcQueryError> {
50    run(std::env::args_os().skip(1))
51}
52
53/// Run the CLI from an argument iterator.
54pub fn run<I>(args: I) -> Result<(), IcQueryError>
55where
56    I: IntoIterator<Item = OsString>,
57{
58    let args = args.into_iter().collect::<Vec<_>>();
59    if first_arg_is_help(&args) {
60        println!("{}", usage());
61        return Ok(());
62    }
63    if let Some(option) = command_local_global_option(&args) {
64        return Err(IcQueryError::Usage(format!(
65            "{option} is a top-level option; put it before the command\n\n{}",
66            usage()
67        )));
68    }
69
70    let matches = parse_matches_or_usage(top_level_dispatch_command(), args, usage)
71        .map_err(IcQueryError::Usage)?;
72    if matches.get_flag("version") {
73        println!("{}", version_text());
74        return Ok(());
75    }
76    let global_network = string_option(&matches, "network");
77
78    let Some((command, subcommand_matches)) = matches.subcommand() else {
79        return Err(IcQueryError::Usage(usage()));
80    };
81    let mut tail = subcommand_matches
82        .get_many::<OsString>(DISPATCH_ARGS)
83        .map(|values| values.cloned().collect::<Vec<_>>())
84        .unwrap_or_default();
85    apply_global_network(command, &mut tail, global_network);
86    let tail = tail.into_iter();
87
88    match command {
89        "nns" => nns::run(tail).map_err(|err| IcQueryError::Nns(err.to_string())),
90        "sns" => sns::run(tail).map_err(|err| IcQueryError::Sns(err.to_string())),
91        _ => unreachable!("top-level dispatch command only defines known commands"),
92    }
93}
94
95#[must_use]
96pub const fn version_text() -> &'static str {
97    VERSION_TEXT
98}
99
100#[cfg(test)]
101mod tests;