use crate::validation;
use clap::Parser;
#[derive(Parser, Default)]
#[command(name = "netwatch", about = "A modern network traffic monitor")]
#[command(version, long_about = None)]
pub struct Args {
pub devices: Vec<String>,
#[arg(short, long)]
pub list: bool,
#[arg(short = 'a', long = "average", default_value = "300")]
pub average_window: u32,
#[arg(short = 'i', long = "incoming", default_value = "0")]
pub max_incoming: u64,
#[arg(short = 'o', long = "outgoing", default_value = "0")]
pub max_outgoing: u64,
#[arg(short = 't', long = "interval", default_value = "1000")]
pub refresh_interval: u64,
#[arg(
long = "high-perf",
help = "Enable high performance mode (slower updates, less CPU)"
)]
pub high_performance: bool,
#[arg(short = 'u', long = "unit", default_value = "k")]
pub traffic_unit: TrafficUnit,
#[arg(short = 'U', long = "data-unit", default_value = "M")]
pub data_unit: DataUnit,
#[arg(short = 'm', long = "multiple")]
pub multiple_devices: bool,
#[arg(short = 'f', long = "file")]
pub log_file: Option<String>,
#[arg(long)]
pub test: bool,
#[arg(long)]
pub debug_dashboard: bool,
#[arg(long)]
pub show_comparison: bool,
#[arg(long)]
pub show_overview: bool,
#[arg(long)]
pub force_terminal: bool,
#[arg(long)]
pub sre_terminal: bool,
}
#[derive(clap::ValueEnum, Clone, Debug, PartialEq, Default)]
pub enum TrafficUnit {
#[value(name = "h")]
#[default]
HumanBit, #[value(name = "H")]
HumanByte, #[value(name = "b")]
Bit, #[value(name = "B")]
Byte, #[value(name = "k")]
KiloBit, #[value(name = "K")]
KiloByte, #[value(name = "m")]
MegaBit, #[value(name = "M")]
MegaByte, #[value(name = "g")]
GigaBit, #[value(name = "G")]
GigaByte, }
pub use TrafficUnit as DataUnit;
impl Args {
pub fn validate(&self) -> crate::error::Result<()> {
for device in &self.devices {
validation::validate_interface_name(device)?;
}
validation::validate_refresh_interval(self.refresh_interval)?;
validation::validate_bandwidth(self.max_incoming)?;
validation::validate_bandwidth(self.max_outgoing)?;
if let Some(ref log_file) = self.log_file {
if log_file != "-" {
validation::validate_file_path(log_file, Some("log"))?;
}
}
Ok(())
}
}
impl TrafficUnit {
#[must_use]
pub fn next(&self) -> Self {
match self {
Self::HumanBit => Self::HumanByte,
Self::HumanByte => Self::Bit,
Self::Bit => Self::Byte,
Self::Byte => Self::KiloBit,
Self::KiloBit => Self::KiloByte,
Self::KiloByte => Self::MegaBit,
Self::MegaBit => Self::MegaByte,
Self::MegaByte => Self::GigaBit,
Self::GigaBit => Self::GigaByte,
Self::GigaByte => Self::HumanBit,
}
}
#[must_use]
pub fn to_string(&self) -> &'static str {
match self {
Self::HumanBit => "h",
Self::HumanByte => "H",
Self::Bit => "b",
Self::Byte => "B",
Self::KiloBit => "k",
Self::KiloByte => "K",
Self::MegaBit => "m",
Self::MegaByte => "M",
Self::GigaBit => "g",
Self::GigaByte => "G",
}
}
#[must_use]
pub fn from_string(s: &str) -> Option<Self> {
match s {
"h" => Some(Self::HumanBit),
"H" => Some(Self::HumanByte),
"b" => Some(Self::Bit),
"B" => Some(Self::Byte),
"k" => Some(Self::KiloBit),
"K" => Some(Self::KiloByte),
"m" => Some(Self::MegaBit),
"M" => Some(Self::MegaByte),
"g" => Some(Self::GigaBit),
"G" => Some(Self::GigaByte),
_ => None,
}
}
}