use crate::cli::pcap::PcapDumpOpts;
use crate::cli::unit::UnitOpts;
use crate::cli::vanity::VanityOpts;
use crate::cli::wallet::WalletOpts;
use crate::debug::parse_pcap_log_file_to_csv;
use crate::node::node_with_autodiscovery;
use address::AddressOpts;
use anyhow::anyhow;
use clap::Clap;
use phrase::PhraseOpts;
use private::PrivateOpts;
use public::PublicOpts;
use seed::SeedOpts;
use std::io;
use std::io::Read;
use std::path::PathBuf;
use std::str::FromStr;
use tracing::Level;
use tracing_subscriber::EnvFilter;
mod address;
mod pcap;
mod phrase;
mod private;
mod public;
mod seed;
mod unit;
mod vanity;
mod wallet;
#[derive(Clap)]
#[clap(author, about, version)]
struct Opts {
#[clap(subcommand)]
command: Command,
#[clap(long)]
no_color: bool,
#[clap(long)]
log_level: Option<Level>,
}
#[derive(Clap)]
enum Command {
Node(NodeOpts),
Unit(UnitOpts),
Wallet(WalletOpts),
Phrase(PhraseOpts),
Seed(SeedOpts),
Private(PrivateOpts),
Public(PublicOpts),
Address(AddressOpts),
Vanity(VanityOpts),
Pcap(PcapDumpOpts),
Debug(DebugOpts),
}
#[derive(Clap)]
struct NodeOpts {
#[clap(short, long)]
override_peers: Option<Vec<String>>,
}
#[derive(Clap)]
struct DebugOpts {
#[clap(subcommand)]
command: DebugCommand,
}
#[derive(Clap)]
enum DebugCommand {
PcapLogToCSV(PcapLogToCsvArgs),
}
#[derive(Clap)]
struct PcapLogToCsvArgs {
src: PathBuf,
dst: PathBuf,
}
pub async fn run() -> anyhow::Result<()> {
let opts = Opts::parse();
let mut filter = EnvFilter::from_default_env();
if let Some(level) = opts.log_level {
filter = filter.add_directive(level.into());
}
let subscriber = tracing_subscriber::fmt::Subscriber::builder()
.with_env_filter(filter)
.with_ansi(!opts.no_color)
.finish();
tracing::subscriber::set_global_default(subscriber).expect("Could not initialize logger");
match opts.command {
#[cfg(feature = "node")]
Command::Node(o) => node_with_autodiscovery(o.override_peers).await,
#[cfg(not(feature = "node"))]
Command::Node(_) => panic!("Compile with the `node` feature to enable this."),
#[cfg(feature = "pcap")]
Command::Pcap(o) => o.handle().await,
#[cfg(not(feature = "pcap"))]
Command::Pcap(o) => panic!("Compile with the `pcap` feature to enable this."),
Command::Debug(debug) => match debug.command {
DebugCommand::PcapLogToCSV(huh) => parse_pcap_log_file_to_csv(&huh.src, &huh.dst),
},
Command::Wallet(wallet) => wallet.handle().await,
Command::Seed(seed) => seed.handle(),
Command::Private(private) => private.handle(),
Command::Public(public) => public.handle(),
Command::Phrase(phrase) => phrase.handle(),
Command::Address(address) => address.handle(),
Command::Unit(unit) => unit.handle(),
Command::Vanity(vanity) => vanity.handle().await,
}
}
#[derive(Copy, Clone)]
enum StringOrStdin<T>
where
T: FromStr,
<T as FromStr>::Err: std::fmt::Debug,
{
String(T),
Stdin,
}
impl<T> StringOrStdin<T>
where
T: FromStr,
<T as FromStr>::Err: std::fmt::Debug,
{
pub fn resolve(self) -> anyhow::Result<T>
where
T: FromStr,
<T as FromStr>::Err: std::fmt::Debug,
{
match self {
StringOrStdin::String(t) => Ok(t),
StringOrStdin::Stdin => {
let mut buffer = String::new();
io::stdin().read_to_string(&mut buffer)?;
Ok(T::from_str(buffer.trim())
.map_err(|e| anyhow!("Conversion from string failed: {:?}", e))?)
}
}
}
}
impl<T> FromStr for StringOrStdin<T>
where
T: FromStr,
<T as FromStr>::Err: std::fmt::Debug,
{
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.as_ref() {
"-" => Ok(StringOrStdin::Stdin),
x => match T::from_str(x) {
Ok(x) => Ok(StringOrStdin::String(x)),
Err(e) => Err(anyhow!("Could not parse string: {:?}", e)),
},
}
}
}