use clap::Parser;
use i0::Timestamp;
#[cfg(feature = "v2")]
use i0::v2;
#[cfg(feature = "v3")]
use i0::v3;
use std::{num::NonZero, process::exit, sync::Arc, thread};
#[derive(Parser, Debug)]
#[command(about = "digs for a vanity thei.rs/i0", long_about = None)]
struct Cli {
#[arg(short, long)]
designation: Option<String>,
#[arg(short, long)]
timestamp: Option<String>,
#[arg()]
needle: String,
#[arg(short, long, default_value_t = 3)]
version: u8,
#[arg(short, long)]
nproc: Option<NonZero<usize>>,
}
fn main() {
let cli = Cli::parse();
let designation = Arc::new(cli.designation.unwrap_or_default());
let timestamp = cli
.timestamp
.map(|s| {
Timestamp::try_from_hex(s.as_ref())
.expect("timestamp in an invalid format; should be hex")
})
.unwrap_or_else(Timestamp::new);
let version = cli.version;
let needle = Arc::new(cli.needle.to_ascii_lowercase());
if needle.len() != 7 || !needle.chars().all(|c| c.is_ascii_hexdigit()) {
eprintln!("invalid needle, needs to be 7 hex characters");
exit(1)
}
let nproc = cli
.nproc
.unwrap_or_else(|| thread::available_parallelism().expect("unable to determine parallelism, manually specify the number of threads to run using -n"))
.get();
println!("looking for i0:{version} '{needle}' with {nproc} threads");
let threads: Vec<_> = (0..nproc)
.map(|_| {
thread::spawn({
let needle = Arc::clone(&needle);
let designation = Arc::clone(&designation);
move || {
match version {
#[cfg(feature = "v2")]
2 => v2::dig(&needle, &designation, timestamp),
#[cfg(feature = "v3")]
3 => v3::dig(&needle, &designation, timestamp),
_ => panic!("version {version} hasn't been implemented"),
};
exit(0)
}
})
})
.collect();
for handle in threads {
let _ = handle.join();
}
}