use std::{
error::Error,
io::{stdin, IsTerminal},
};
use clap::{CommandFactory, Parser, Subcommand};
use fcidr::{Cidr, Fcidr};
#[derive(Debug, Parser)]
#[command(about, author, version, long_about = None)]
struct Cli {
cidr: Option<Cidr>,
#[command(subcommand)]
command: FcidrCommand,
}
#[derive(Debug, Subcommand)]
enum FcidrCommand {
#[command(visible_alias = "!", visible_alias = "not")]
Complement,
#[command(
visible_alias = "-",
visible_alias = "exclude",
visible_alias = "minus"
)]
Difference {
cidr: Cidr,
},
#[command(visible_alias = ">", visible_alias = "contains")]
Superset { cidr: Cidr },
#[command(visible_alias = "+", visible_alias = "include", visible_alias = "plus")]
Union {
cidr: Cidr,
},
}
fn main() -> Result<(), Box<dyn Error>> {
let cli = Cli::parse();
let mut fcidr: Fcidr = if let Some(cidr) = cli.cidr {
Fcidr::new(cidr)
} else {
if stdin().is_terminal() {
Cli::command().print_help().unwrap();
::std::process::exit(2);
}
stdin().lines().fold(
Ok(Fcidr::default()),
|fcidr: Result<Fcidr, Box<dyn Error>>, l| {
if let Ok(mut fcidr) = fcidr {
fcidr.union(l?.parse()?);
return Ok(fcidr);
}
fcidr
},
)?
};
match cli.command {
FcidrCommand::Complement => fcidr.complement(),
FcidrCommand::Difference { cidr } => fcidr.difference(cidr),
FcidrCommand::Superset { cidr } => {
if fcidr.is_superset(cidr) {
return Ok(());
}
return Err(format!("not a superset of {cidr}").into());
}
FcidrCommand::Union { cidr } => fcidr.union(cidr),
};
for cidr in fcidr {
println!("{cidr}");
}
Ok(())
}