btpeer 0.3.0

Simple CLI tool to get peers from TCP/HTTP and UDP BitTorrent trackers
use clap::Parser;

#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
pub struct Config {
    /// UDP tracker HOST:PORT
    #[arg(short, long)]
    pub udp_tracker: Option<Vec<std::net::SocketAddr>>,
    /// TCP/HTTP tracker URL
    #[arg(short = 'H', long)]
    pub http_tracker: Option<Vec<url::Url>>,
    /// Socket read timeout
    #[arg(short, long, default_value_t = 5)]
    pub timeout: u64,
    /// Info-hash subject
    #[arg(short, long, value_parser = info_hash_v1)]
    pub info_hash: [u8; 20],
    /// Bind port for outgoing connections
    #[arg(long, default_value_t = 6881)]
    pub port: u16,
}

fn info_hash_v1(s: &str) -> Result<[u8; 20], String> {
    if s.len() != 40 {
        return Err("Info-hash v1 must be exactly 40 hex characters long".to_string());
    }

    let mut bytes = [0u8; 20];

    for (i, b) in bytes.iter_mut().enumerate() {
        let start = i * 2;
        *b = u8::from_str_radix(&s[start..start + 2], 16)
            .map_err(|e| format!("Invalid hex character at index {start}: {e}"))?;
    }

    Ok(bytes)
}