rcpufetch 0.0.5

[ALPHA] A rusty crossplatform, but simple CLI binutil for reading CPU information.
mod art;
mod bsd;
mod cla;
mod cpu;
mod linux;
mod macos;
mod report;
mod style;
mod windows;

use std::env;

fn main() {
    let args = match cla::Args::parse() {
        Ok(args) => args,
        Err(e) => {
            eprintln!("{}", e);
            eprintln!("Try 'rcpufetch --help' for more information.");
            std::process::exit(1);
        }
    };

    if args.help {
        cla::print_help();
        return;
    }
    if args.version {
        cla::print_version();
        return;
    }
    if args.license {
        cla::print_license();
        return;
    }
    if let Some(shell) = args.completions {
        cla::print_completions(&shell);
        return;
    }

    if args.raw && !cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
        eprintln!("Error: --raw is only valid on x86/x86_64");
        std::process::exit(1);
    }

    let logo_override = args.logo.as_ref().and_then(|logo| {
        match logo.to_lowercase().as_str() {
            "nvidia" => Some("NVIDIA"),
            "powerpc" => Some("PowerPC"),
            "arm" => Some("ARM"),
            "amd" => Some("AuthenticAMD"),
            "intel" => Some("GenuineIntel"),
            "apple" => Some("Apple"),
            _ => {
                eprintln!("Warning: Unknown logo vendor '{}'. Valid options: nvidia, powerpc, arm, amd, intel, apple", logo);
                None
            }
        }
    });

    let os = env::consts::OS;

    macro_rules! run {
        ($ctor:expr) => {
            match $ctor {
                Ok(cpu_info) => {
                    if args.debug {
                        print_debug();
                    } else if args.raw {
                        print_raw();
                    } else {
                        report::print(&cpu_info.to_report(), &args, logo_override);
                    }
                }
                Err(e) => {
                    eprintln!("Error fetching CPU info: {}", e);
                    std::process::exit(1);
                }
            }
        };
    }

    match os {
        "linux" => run!(linux::linux::LinuxCpuInfo::new()),
        "windows" => run!(windows::windows::WindowsCpuInfo::new()),
        "macos" => run!(macos::macos::MacOSCpuInfo::new()),
        "freebsd" | "openbsd" => run!(bsd::BsdCpuInfo::new()),
        _ => {
            eprintln!("Unsupported operating system: {}", os);
            std::process::exit(1);
        }
    }
}

/// `-d`/`--debug`: print low-level identifying register info and exit, mirroring
/// cpufetch's `print_debug` (cpuid family/model/stepping on x86; MIDR-derived info is
/// gathered per-OS so isn't available here in the generic path).
fn print_debug() {
    cla::print_version();
    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
    {
        let info = cpu::x86::detect();
        println!("vendor: {:?}", info.vendor);
        println!("uarch: {:?}", info.uarch);
        println!("process_nm: {:?}", info.process_nm);
        println!("features: {:?}", info.features);
    }
    #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
    {
        println!("--debug output is currently x86-only in rcpufetch");
    }
}

/// `-r`/`--raw` (x86 only): dump raw cpuid leaves instead of the normal report.
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn print_raw() {
    cla::print_version();
    let info = cpu::x86::detect();
    println!("brand_string: {:?}", cpu::x86::brand_string());
    println!("vendor: {:?}", info.vendor);
    println!("uarch: {:?}", info.uarch);
    println!("process_nm: {:?}", info.process_nm);
    println!("features: {:?}", info.features);
}

#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
fn print_raw() {
    eprintln!("Error: --raw is only valid on x86/x86_64");
    std::process::exit(1);
}