//! 字节数人类可读格式化
//!
//! 把字节数拆成人类可读的 `(数值, 单位)`，全程整数运算、不引浮点（契合 `no_std` / softfloat）。
//! 精确版 [`human_size`] 选能整除的最大单位；舍入版 [`human_round`] 给到十分位。
//!
//! 2 的幂尺寸常量见 `moa_sizes`，对齐原语见 `moa_align`。

#![no_std]

use moa_sizes::{SZ_1G, SZ_1K, SZ_1M};

/// 把字节数按**最大可整除**的 2 次幂单位拆成 `(数值, 单位后缀)`，供人类可读打印。
///
/// 选能整除 `bytes` 的最大单位（GiB→MiB→KiB→B），全程整数、不引入浮点（契合 `no_std` /
/// softfloat 目标，且尺寸恒精确无舍入）。单位用 IEC 二进制后缀（KiB=1024B…）以消歧义。
/// 例：`SZ_128K → (128, "KiB")`、`0x135400 → (1237, "KiB")`、`0 → (0, "B")`。
///
/// ⚠️ **如果是内核调用，则仅限内核启动期调用，仅限内核启动期调用**：本函数在 `.init.text`
/// 段（`#[moa_sec_macros::init]`）， `free_initmem` 后段被整体回收，运行期调用即跳入已释放内存。
#[moa_sec_macros::init]
pub fn human_size(bytes: usize) -> (usize, &'static str) {
    if bytes != 0 && bytes.is_multiple_of(SZ_1G) {
        (bytes / SZ_1G, "GiB")
    } else if bytes != 0 && bytes.is_multiple_of(SZ_1M) {
        (bytes / SZ_1M, "MiB")
    } else if bytes != 0 && bytes.is_multiple_of(SZ_1K) {
        (bytes / SZ_1K, "KiB")
    } else {
        (bytes, "B")
    }
}

/// 把字节数**舍入**成 `(整数部分, 十分位, 单位)`（GiB/MiB/KiB），供量级可读打印（对照精确版
/// [`human_size`]）。选 ≤ `bytes` 的最大单位（< 1 MiB 一律按 KiB，含亚 K 显示为 `0.x KiB`），
/// 十分位四舍五入，全程整数运算、不引浮点（契合 `no_std` / softfloat）。十分位进位到 10 时
/// 回填整数部分（如 `1023.95KiB → 1024.0KiB`）。例：`0x4f440 → (317, 1, "KiB")`、`0 → (0, 0,
/// "KiB")`。
///
/// 适用于尺寸已在别处精确给出（如 dump 的 `[base-end]` 区间）、本列仅需看量级的场景；需要精确
/// 无舍入时用 [`human_size`]。
///
/// ⚠️ **如果是内核调用，则仅限内核启动期调用**：同 [`human_size`]，位于
/// `.init.text`，`free_initmem` 后不可再调。
#[moa_sec_macros::init]
pub fn human_round(bytes: usize) -> (usize, usize, &'static str) {
    let (div, unit) = if bytes >= SZ_1G {
        (SZ_1G, "GiB")
    } else if bytes >= SZ_1M {
        (SZ_1M, "MiB")
    } else {
        (SZ_1K, "KiB")
    };
    let mut whole = bytes / div;
    let mut tenths = (bytes % div * 10 + div / 2) / div;
    if tenths == 10 {
        whole += 1;
        tenths = 0;
    }
    (whole, tenths, unit)
}
