1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
use std::fmt::Write; use std::time::Duration; pub fn format_micros(micros: i32, f: &mut dyn std::fmt::Write) -> std::fmt::Result { return if micros < 1_000 { write!(f, "{} us", micros) } else if micros < 10_000 { write!(f, "{:.2} ms", micros as f32 / 1_000.) } else if micros < 100_000 { write!(f, "{:.1} ms", micros as f32 / 1_000.) } else if micros < 1_000_000 { write!(f, "{} ms", micros / 1_000) } else if micros < 10_000_000 { write!(f, "{:.2} s", micros as f32 / 1_000_000.) } else if micros < 100_000_000 { write!(f, "{:.1} s", micros as f32 / 1_000_000.) } else { write!(f, "{} s", micros / 1_000_000) }; } pub fn format_short_duration(duration_in_micros: i32) -> String { let mut result = String::new(); let _ = format_micros(duration_in_micros, &mut result); return result; } pub fn format_bytes(size_in_bytes: usize, f: &mut dyn std::fmt::Write) -> std::fmt::Result { if size_in_bytes == 1 { return write!(f, "1 byte"); } else if size_in_bytes < 1024 { return write!(f, "{} bytes", size_in_bytes); } let mut magnitude = 0; let mut size = size_in_bytes as f32; while size > 1024. && magnitude < 5 { size /= 1024.; magnitude += 1; } if size <= 10. { write!(f, "{:2} ", size)?; } else if size <= 100. { write!(f, "{:1} ", size)?; } else { write!(f, "{:0} ", size)?; } match magnitude { 0 => write!(f, "Bytes"), 1 => write!(f, "KiB"), 2 => write!(f, "MiB"), 3 => write!(f, "GiB"), 4 => write!(f, "TiB"), _ => write!(f, "PiB"), } } pub fn format_size(size_in_bytes: usize) -> String { let mut result = String::new(); let _ = format_bytes(size_in_bytes, &mut result); return result; } pub fn parse_size(str: impl AsRef<str>) -> anyhow::Result<usize> { lazy_static::lazy_static! { static ref NUMBER_AND_SUFFIX: regex::Regex = regex::Regex::new(r"^ *(\d+) *([kKmMgGtT]?).*").unwrap(); } match NUMBER_AND_SUFFIX.captures(str.as_ref()) { Some(captures) => { let number = captures[1].parse::<usize>().unwrap(); match &captures[2] { "k" | "K" => Ok(number * 1024), "m" | "M" => Ok(number * 1024* 1024), "g" | "G" => Ok(number * 1024* 1024* 1024), "t" | "T" => Ok(number * 1024* 1024* 1024* 1024), _ => Ok(number) } } None => Err(anyhow::anyhow!("Cannot parse '{}' into a size expression. Only 'k', 'm', 'g' and 't' are accepted as suffixes.", str.as_ref())) } } pub fn parse_duration(str: impl AsRef<str>) -> anyhow::Result<Duration> { lazy_static::lazy_static! { static ref NUMBER_AND_SUFFIX: regex::Regex = regex::Regex::new(r"^ *(\d+) *((ms|s|m|h|d|MS|S|M|H|D)?).*").unwrap(); } match NUMBER_AND_SUFFIX.captures(str.as_ref()) { Some(captures) => { let number = captures[1].parse::<u64>().unwrap(); match &captures[2] { "s" | "S" => Ok(Duration::from_secs(number)), "m" | "M" => Ok(Duration::from_secs(number * 60)), "h" | "H" => Ok(Duration::from_secs(number * 60 * 60)), "d" | "D" => Ok(Duration::from_secs(number * 60 * 60 * 24)), _ => Ok(Duration::from_millis(number)) } } None => Err(anyhow::anyhow!("Cannot parse '{}' into a duration expression. Only 'ms', 's', 'm', 'h' and 'd' are accepted as suffixes.", str.as_ref())) } } pub fn format_duration(duration: Duration) -> String { let mut result = String::new(); let mut value = duration.as_millis(); { let days = value / (1000 * 60 * 60 * 24); if days > 0 { let _ = write!(result, "{}d", days); value = value % (1000 * 60 * 60 * 24); } } { let hours = value / (1000 * 60 * 60); if hours > 0 { if !result.is_empty() { result.push(' '); } let _ = write!(result, "{}h", hours); value = value % (1000 * 60 * 60); } } { let minutes = value / (1000 * 60); if minutes > 0 { if !result.is_empty() { result.push(' '); } let _ = write!(result, "{}m", minutes); value = value % (1000 * 60); } } { let seconds = value / 1000; if seconds > 0 { if !result.is_empty() { result.push(' '); } let _ = write!(result, "{}s", seconds); value = value % 1000 * 60; } } if value > 0 { if !result.is_empty() { result.push(' '); } let _ = write!(result, "{}ms", value); } result }