1#[must_use]
11pub fn truncate(s: &str, max_chars: usize) -> String {
12 let mut chars = s.chars();
13 let truncated: String = chars.by_ref().take(max_chars).collect();
14
15 if chars.next().is_some() {
16 truncated
17 } else {
18 s.to_string()
19 }
20}
21
22#[must_use]
28#[expect(clippy::cast_precision_loss)]
29pub fn byte_size(bytes: u64) -> String {
30 const UNITS: [&str; 5] = ["B", "KiB", "MiB", "GiB", "TiB"];
31
32 let mut value = bytes as f64;
33 let mut unit_index = 0usize;
34
35 while value >= 1024.0 && unit_index < UNITS.len() - 1 {
36 value /= 1024.0;
37 unit_index += 1;
38 }
39
40 format!("{value:.2} {}", UNITS[unit_index])
41}
42
43#[cfg(test)]
48mod tests {
49 use super::{byte_size, truncate};
50
51 #[test]
52 fn keeps_short_strings() {
53 assert_eq!(truncate("root", 9), "root");
54 assert_eq!(truncate("abcdefgh", 9), "abcdefgh");
55 assert_eq!(truncate("abcdefghi", 9), "abcdefghi");
56 }
57
58 #[test]
59 fn truncates_long_strings() {
60 assert_eq!(truncate("abcdefghijkl", 9), "abcdefghi");
61 assert_eq!(truncate("abcdefghijklmnopqrstuvwxyz", 9), "abcdefghi");
62 }
63
64 #[test]
65 fn formats_small_byte_sizes() {
66 assert_eq!(byte_size(0), "0.00 B");
67 assert_eq!(byte_size(512), "512.00 B");
68 assert_eq!(byte_size(1024), "1.00 KiB");
69 }
70
71 #[test]
72 fn formats_larger_byte_sizes() {
73 assert_eq!(byte_size(720_795), "703.90 KiB");
74 assert_eq!(byte_size(13_936_529), "13.29 MiB");
75 assert_eq!(byte_size(9_102_643), "8.68 MiB");
76 }
77}