image_optimizer/file_ops/
byte_formatter.rs

1/// Formats a byte count into a human-readable string with appropriate units.
2///
3/// This function converts raw byte counts into a more readable format using
4/// standard binary units (B, KB, MB, GB). It automatically selects the most
5/// appropriate unit and formats the output with appropriate decimal precision.
6///
7/// # Arguments
8///
9/// * `bytes` - The number of bytes to format
10///
11/// # Returns
12///
13/// A formatted string representation of the byte count with units.
14/// - Bytes are shown as whole numbers (e.g., "512 B")
15/// - Larger units are shown with one decimal place (e.g., "1.5 KB")
16///
17/// # Examples
18///
19/// ```rust
20/// use image_optimizer::file_ops::format_bytes;
21///
22/// assert_eq!(format_bytes(512), "512 B");
23/// assert_eq!(format_bytes(1024), "1.0 KB");
24/// assert_eq!(format_bytes(1536), "1.5 KB");
25/// assert_eq!(format_bytes(1048576), "1.0 MB");
26/// ```
27#[must_use]
28pub fn format_bytes(bytes: u64) -> String {
29    const UNITS: &[&str] = &["B", "KB", "MB", "GB"];
30    #[allow(clippy::cast_precision_loss)]
31    let mut size = bytes as f64;
32    let mut unit_index = 0;
33
34    while size >= 1024.0 && unit_index < UNITS.len() - 1 {
35        size /= 1024.0;
36        unit_index += 1;
37    }
38
39    if unit_index == 0 {
40        format!("{} {}", bytes, UNITS[unit_index])
41    } else {
42        format!("{:.1} {}", size, UNITS[unit_index])
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn test_format_bytes() {
52        assert_eq!(format_bytes(0), "0 B");
53        assert_eq!(format_bytes(512), "512 B");
54        assert_eq!(format_bytes(1023), "1023 B");
55        assert_eq!(format_bytes(1024), "1.0 KB");
56        assert_eq!(format_bytes(1536), "1.5 KB");
57        assert_eq!(format_bytes(1048576), "1.0 MB");
58        assert_eq!(format_bytes(1073741824), "1.0 GB");
59        assert_eq!(format_bytes(2147483648), "2.0 GB");
60    }
61
62    #[test]
63    fn test_format_bytes_edge_cases() {
64        assert_eq!(format_bytes(u64::MAX), "17179869184.0 GB");
65        assert_eq!(format_bytes(1), "1 B");
66        assert_eq!(format_bytes(1025), "1.0 KB");
67    }
68}