i0 0.1.0

thei.rs/i0 reference implementation written in rust
use clap::Parser;
use i0::Timestamp;
#[cfg(feature = "v2")]
use i0::v2;
#[cfg(feature = "v3")]
use i0::v3;
use std::sync::Arc;
use std::thread;

#[derive(Parser, Debug)]
#[command(about = "generates a new thei.rs/i0", long_about = None)]
struct Cli {
    /// user-defined designation
    #[arg(short, long)]
    designation: Option<String>,

    /// creation timestamp (used for migrating from older versions)
    #[arg(short, long)]
    timestamp: Option<String>,

    /// the short i0 to search for
    #[arg()]
    needle: String,

    /// which version of the specification to use
    #[arg(short, long, default_value_t = 3)]
    version: u8,
}

fn main() {
    // parse args
    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);

    let nproc = thread::available_parallelism().unwrap().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"),
                    };
                    std::process::exit(0);
                }
            })
        })
        .collect();

    for handle in threads {
        let _ = handle.join();
    }
}