//
// Syd: rock-solid unikernel
// src/syd-cpu.rs: Print the number of CPUs.
//
// Copyright (c) 2024 Ali Polatel <alip@chesswob.org>
//
// SPDX-License-Identifier: GPL-3.0-or-later

use std::{env, process::ExitCode};

use getargs::{Opt, Options};
use syd::err::SydResult;

// Set global allocator to mimalloc.
#[global_allocator]
static GLOBAL: mimalloc2_rust::GlobalMiMalloc = mimalloc2_rust::GlobalMiMalloc;

fn main() -> SydResult<ExitCode> {
    syd::set_sigpipe_dfl()?;

    // Configure mimalloc.
    syd::configure_mimalloc();

    let args = env::args().skip(1).collect::<Vec<_>>();
    let args: &'static Vec<String> = Box::leak(Box::new(args));
    let mut opts = Options::new(args.iter().map(String::as_str));
    let mut physical = false;

    while let Some(opt) = opts.next_opt()? {
        match opt {
            Opt::Short('h') => {
                help();
                return Ok(ExitCode::SUCCESS);
            }
            Opt::Short('l') => {
                physical = false;
            }
            Opt::Short('p') => {
                physical = true;
            }
            Opt::Short(opt) => {
                eprintln!("Unknown option: -{opt}!");
                return Ok(ExitCode::FAILURE);
            }
            Opt::Long(opt) => {
                eprintln!("Unknown option: --{opt}!");
                return Ok(ExitCode::FAILURE);
            }
        }
    }

    let num = if physical {
        num_cpus::get_physical()
    } else {
        num_cpus::get()
    };
    println!("{num}");

    Ok(ExitCode::SUCCESS)
}

fn help() {
    println!("Usage: syd-cpu [-hlp]");
    println!("Print the number of CPUs.");
    println!("Use -l to print the number of logical CPUs (default).");
    println!("Use -p to print the number of physical CPUs.");
}
