1use clap::Parser;
2use std::env;
3
4const AUTHOR: &str = env!("CARGO_PKG_AUTHORS");
5const VERSION: &str = env!("CARGO_PKG_VERSION");
6const REPO_URL: &str = env!("CARGO_PKG_REPOSITORY");
7const LICENSE: &str = env!("CARGO_PKG_LICENSE");
8
9lazy_static::lazy_static! {
10 static ref LONG_VERSION: String = {
11 let commit_hash = option_env!("VERGEN_GIT_SHA").unwrap_or("unknown");
13 let git_dirty = option_env!("VERGEN_GIT_DIRTY").unwrap_or("unknown");
14 let build_timestamp = option_env!("VERGEN_BUILD_TIMESTAMP").unwrap_or("unknown");
15 let rust_version = option_env!("VERGEN_RUSTC_SEMVER").unwrap_or("unknown");
16 let target = env::var("TARGET").unwrap_or_else(|_| "unknown".to_string());
17
18 let commit_str = if commit_hash.starts_with("VERGEN") {
20 "non-git build".to_string()
21 } else {
22 let suffix = if git_dirty == "false" { "" } else { "-dirty" };
23 format!("{}{}", commit_hash, suffix)
24 };
25
26 format!(
27 "A tool to report network interface statistics.\n\n\
28 Author: {}\n\
29 Repo: {}\n\
30 License: {}\n\
31 Commit: {}\n\
32 Build Timestamp: {}\n\
33 Rust Version: {}\n\
34 Compilation Target: {}",
35 AUTHOR, REPO_URL, LICENSE, commit_str, build_timestamp, rust_version, target
36 )
37 };
38}
39
40#[derive(Parser)]
41#[clap(version = VERSION, author = AUTHOR, long_version = LONG_VERSION.as_str())]
42pub struct Opts {
43 #[clap(short, long)]
45 pub interfaces: Option<String>,
46
47 #[clap(short = 'a')]
49 pub monitor_all: bool,
50
51 #[clap(short = 'l')]
53 pub monitor_loopback: bool,
54
55 #[clap(
57 short = 'z',
58 default_value_if("cfg(target_os = \"windows\")", "false", "true")
59 )]
60 pub hide_zero_counters: bool,
61
62 #[clap(long)]
64 pub list_interfaces: bool,
65
66 #[arg(long, value_parser = parse_non_negative_f64)]
68 pub first_measurement: Option<f64>,
69
70 #[arg(default_value = "1", value_parser = parse_positive_f64)]
72 pub delay: f64,
73
74 #[arg(value_parser = parse_positive_u64)]
76 pub count: Option<u64>,
77}
78
79fn parse_positive_f64(src: &str) -> Result<f64, String> {
80 let val: f64 = src
81 .parse()
82 .map_err(|_| format!("`{}` is not a valid number", src))?;
83 if val <= 0.0 {
84 Err(format!("`{}` must be greater than 0", src))
85 } else {
86 Ok(val)
87 }
88}
89
90fn parse_non_negative_f64(src: &str) -> Result<f64, String> {
91 let val: f64 = src
92 .parse()
93 .map_err(|_| format!("`{}` is not a valid number", src))?;
94 if val < 0.0 {
95 Err(format!("`{}` must be greater than or equal to 0", src))
96 } else {
97 Ok(val)
98 }
99}
100
101fn parse_positive_u64(src: &str) -> Result<u64, String> {
102 let val: u64 = src
103 .parse()
104 .map_err(|_| format!("`{}` is not a valid number > 0", src))?;
105 if val == 0 {
106 Err(format!("`{}` must be greater than 0", src))
107 } else {
108 Ok(val)
109 }
110}