Skip to main content

rlmctl_common/
util.rs

1use crate::{CpuLimit, IoLimit, Limit, MemoryLimit, Result};
2
3/// Build a Limit from optional string values
4pub fn build_limit(
5    memory: Option<&str>,
6    cpu: Option<&str>,
7    io_read: Option<&str>,
8    io_write: Option<&str>,
9) -> Result<Limit> {
10    let memory = memory
11        .filter(|s| !s.is_empty())
12        .map(MemoryLimit::parse)
13        .transpose()?;
14
15    let cpu = cpu
16        .filter(|s| !s.is_empty())
17        .map(CpuLimit::parse)
18        .transpose()?;
19
20    let read_bps = io_read
21        .filter(|s| !s.is_empty())
22        .map(IoLimit::parse_bps)
23        .transpose()?;
24
25    let write_bps = io_write
26        .filter(|s| !s.is_empty())
27        .map(IoLimit::parse_bps)
28        .transpose()?;
29
30    let io = if read_bps.is_some() || write_bps.is_some() {
31        Some(IoLimit {
32            read_bps,
33            write_bps,
34        })
35    } else {
36        None
37    };
38
39    // Note: Zero validation happens at parse time in MemoryLimit/CpuLimit/IoLimit
40
41    Ok(Limit { memory, cpu, io })
42}
43
44/// Format bytes as human-readable string
45pub fn format_bytes(bytes: u64) -> String {
46    const KB: u64 = 1024;
47    const MB: u64 = KB * 1024;
48    const GB: u64 = MB * 1024;
49    const TB: u64 = GB * 1024;
50
51    if bytes >= TB {
52        format!("{:.1}T", bytes as f64 / TB as f64)
53    } else if bytes >= GB {
54        format!("{:.1}G", bytes as f64 / GB as f64)
55    } else if bytes >= MB {
56        format!("{:.1}M", bytes as f64 / MB as f64)
57    } else if bytes >= KB {
58        format!("{:.1}K", bytes as f64 / KB as f64)
59    } else {
60        format!("{bytes}B")
61    }
62}