i0 0.2.0

thei.rs/i0 reference implementation written in rust
Documentation
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 {
    /// 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,

    /// number of threads to use for searching
    #[arg(short, long)]
    nproc: Option<NonZero<usize>>,
}

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.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();
    }
}