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, passthrough_args, string_option},
22    globals::{apply_global_network, command_local_global_option, top_level_dispatch_command},
23    help::{collect_args_or_print_help, usage},
24};
25use std::ffi::OsString;
26use thiserror::Error as ThisError;
27
28const VERSION_TEXT: &str = concat!("icq ", env!("CARGO_PKG_VERSION"));
29
30///
31/// IcQueryError
32///
33#[derive(Debug, ThisError)]
34pub enum IcQueryError {
35    #[error("{0}")]
36    Usage(String),
37
38    #[error("nns: {0}")]
39    Nns(String),
40
41    #[error("sns: {0}")]
42    Sns(String),
43}
44
45/// Run the CLI from process arguments.
46pub fn run_from_env() -> Result<(), IcQueryError> {
47    run(std::env::args_os().skip(1))
48}
49
50/// Run the CLI from an argument iterator.
51pub fn run<I>(args: I) -> Result<(), IcQueryError>
52where
53    I: IntoIterator<Item = OsString>,
54{
55    let Some(args) = collect_args_or_print_help(args, usage) else {
56        return Ok(());
57    };
58    if let Some(option) = command_local_global_option(&args) {
59        return Err(IcQueryError::Usage(format!(
60            "{option} is a top-level option; put it before the command\n\n{}",
61            usage()
62        )));
63    }
64
65    let matches = parse_matches_or_usage(top_level_dispatch_command(), args, usage)
66        .map_err(IcQueryError::Usage)?;
67    if matches.get_flag("version") {
68        println!("{}", version_text());
69        return Ok(());
70    }
71    let global_network = string_option(&matches, "network");
72
73    let Some((command, subcommand_matches)) = matches.subcommand() else {
74        return Err(IcQueryError::Usage(usage()));
75    };
76    let mut tail = passthrough_args(subcommand_matches);
77    apply_global_network(command, &mut tail, global_network);
78    let tail = tail.into_iter();
79
80    match command {
81        "nns" => nns::run(tail).map_err(|err| IcQueryError::Nns(err.to_string())),
82        "sns" => sns::run(tail).map_err(|err| IcQueryError::Sns(err.to_string())),
83        _ => unreachable!("top-level dispatch command only defines known commands"),
84    }
85}
86
87#[must_use]
88pub const fn version_text() -> &'static str {
89    VERSION_TEXT
90}
91
92#[cfg(test)]
93mod tests;