//! 内核命令行参数派发（类比 Linux `__setup` / `early_param`）。
//!
//! 各子系统用 `#[cmdline("key")]`（`moa_sec_macros`）登记 `key=value` 处理器；链接器把条目收进
//! `[__scmdline, __ecmdline)`，启动期 [`parse`] 按空白切分命令行、对含 `=` 的 token 匹配
//! `key` 并调用对应 handler（传入 `=` 右侧字面值）。

#![no_std]

use moa_linksym::{cmdline_end, cmdline_start};

/// 仅供 `#[moa_sec_macros::cmdline]` 展开引用，勿直接使用。
#[doc(hidden)]
pub mod __macro {
    /// 链接段登记表项（由 `#[cmdline]` 生成静态实例）。
    #[derive(Clone, Copy, Debug)]
    #[repr(C)]
    pub struct CmdlineEntry {
        /// 参数名（不含 `=`，如 `"level"`）。
        pub name: &'static str,
        /// 值回调：`value` 为 `=` 右侧未解码字面值。
        pub handler: fn(&str),
    }
}
use __macro::CmdlineEntry;

#[inline]
fn entries() -> &'static [CmdlineEntry] {
    let start = cmdline_start();
    let end = cmdline_end();
    if start >= end {
        return &[];
    }
    let size = size_of::<CmdlineEntry>();
    debug_assert_eq!((end - start) % size, 0, "cmdline table misaligned");
    let count = (end - start) / size;
    // SAFETY: `[__scmdline, __ecmdline)` 由链接脚本界定，元素为 `CmdlineEntry`。
    unsafe { core::slice::from_raw_parts(start as *const CmdlineEntry, count) }
}

/// 解析内核命令行：对每个 `key=value` token，在登记表中查找 `key` 并调用 handler。
///
/// 无 `=` 的 token 忽略（位置参数由 initrd 启动 blob 另行处理）。同名 `key` 多次出现时，
/// 各次均会派发（登记表中同名条目须自行避免重复登记）。
#[inline]
pub fn parse(cmdline: &str) {
    let table = entries();
    if table.is_empty() {
        return;
    }
    for tok in cmdline.split_ascii_whitespace() {
        let Some((key, val)) = tok.split_once('=') else {
            continue;
        };
        for entry in table {
            if entry.name == key {
                (entry.handler)(val);
            }
        }
    }
}
