Skip to main content

yggdrasil/utils/
mod.rs

1//! 通用工具函数子模块。
2//!
3//! - `comment_storage`:评论草稿 localStorage 持久化(WASM 端)。
4//! - `error`:server function 错误转可读失败提示(两端通用)。
5//! - `html`:HTML 转义(两端通用)。
6//! - `js`:WASM 端剪贴板与主题过渡探测(仅 wasm32)。
7//! - `text`:Markdown / 纯文本处理(仅 `server` feature)。
8//! - `time`:跨平台时间/睡眠工具(WASM 与原生异步版本)。
9//! - `toc`:目录 HTML 的一级小节解析(仅 `server` feature)。
10//! - `web_upload`:multipart 文件上传 fetch 助手(仅 wasm32)。
11
12/// 评论草稿 localStorage 持久化(仅在 WASM 端实际读写)。
13pub mod comment_storage;
14/// server function 错误转可读失败提示(前端后端通用)。
15pub mod error;
16/// HTML 转义工具(前端后端通用)。
17pub mod html;
18/// WASM 端剪贴板与主题过渡探测(仅 wasm32 编译)。
19#[cfg(target_arch = "wasm32")]
20pub mod js;
21/// 服务端共享常量与工具(hash、正则、上限)。
22#[cfg(feature = "server")]
23pub mod server;
24/// Markdown / 纯文本处理工具。
25#[cfg(feature = "server")]
26pub mod text;
27/// 跨平台时间/睡眠工具。
28pub mod time;
29/// 已存储目录 HTML 的一级小节解析(服务端)。
30#[cfg(any(feature = "server", test))]
31pub mod toc;
32/// WASM 端 multipart 上传助手(仅 wasm32 编译)。
33#[cfg(target_arch = "wasm32")]
34pub mod web_upload;
35
36/// 字节数 → 人类可读字符串(如 `1.2 MB`)。
37///
38/// 全项目唯一实现:素材管理页、上传列表与系统管理各 tab 共用。
39/// 按 1024 进位取到 TB;不足 1 KB 时原样输出整数 B,其余保留一位小数。
40pub fn format_bytes(bytes: i64) -> String {
41    const UNITS: &[&str] = &["B", "KB", "MB", "GB", "TB"];
42    let mut size = bytes as f64;
43    let mut unit = 0;
44    while size.abs() >= 1024.0 && unit < UNITS.len() - 1 {
45        size /= 1024.0;
46        unit += 1;
47    }
48    if unit == 0 {
49        format!("{} B", bytes)
50    } else {
51        format!("{size:.1} {}", UNITS[unit])
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::format_bytes;
58
59    #[test]
60    fn bytes_under_1k_render_as_integer() {
61        assert_eq!(format_bytes(0), "0 B");
62        assert_eq!(format_bytes(512), "512 B");
63        assert_eq!(format_bytes(1023), "1023 B");
64    }
65
66    #[test]
67    fn kilo_and_mega_render_with_one_decimal() {
68        assert_eq!(format_bytes(1536), "1.5 KB");
69        assert_eq!(format_bytes(1_258_291), "1.2 MB");
70    }
71
72    #[test]
73    fn giga_and_tera_render_with_one_decimal() {
74        assert_eq!(format_bytes(2 * 1024 * 1024 * 1024), "2.0 GB");
75        assert_eq!(format_bytes(3 * 1024_i64.pow(4)), "3.0 TB");
76    }
77
78    #[test]
79    fn values_stop_at_tb() {
80        // 超过 TB 后继续按 TB 表示,不进位到不存在的单位。
81        assert_eq!(format_bytes(2048 * 1024_i64.pow(4)), "2048.0 TB");
82    }
83}