use std::time::{SystemTime, UNIX_EPOCH};
pub(super) const WORKING: &str = "…";
pub(super) fn unix(time: SystemTime) -> u64 {
time.duration_since(UNIX_EPOCH)
.map_or(0, |since| since.as_secs())
}
pub(super) fn clock(time: SystemTime) -> String {
let seconds = unix(time);
format!(
"{:02}:{:02}:{:02}",
seconds / 3600 % 24,
seconds / 60 % 60,
seconds % 60
)
}
pub(super) fn duration(duration: std::time::Duration) -> String {
let seconds = duration.as_secs();
match (seconds / 3600, seconds / 60 % 60) {
(0, 0) => format!("{seconds}s"),
(0, minutes) => format!("{minutes}m"),
(hours, minutes) => format!("{hours}h{minutes:02}m"),
}
}
pub(super) fn cut(text: &str, width: usize) -> String {
if text.chars().count() <= width {
return text.to_string();
}
if width == 0 {
return String::new();
}
let kept: String = text.chars().take(width - 1).collect();
format!("{kept}…")
}
pub(super) fn hang(text: &str, width: u16, indent: usize) -> Vec<String> {
let width = usize::from(width);
let mut lines = Vec::new();
let mut line = " ".repeat(indent);
let mut start = indent;
for word in text.split(' ') {
let used = line.chars().count();
let fresh = used == start;
if !fresh && !word.is_empty() && used + 1 + word.chars().count() > width {
lines.push(std::mem::replace(&mut line, " ".repeat(indent + 2)));
start = indent + 2;
} else if !fresh {
line.push(' ');
}
line.push_str(word);
}
lines.push(line);
lines
}
#[cfg(test)]
mod tests {
use std::time::Duration;
use super::*;
#[test]
fn a_clock_is_utc_hours_minutes_and_seconds() {
let time = UNIX_EPOCH + Duration::from_secs(1_790_000_000);
assert_eq!(clock(time), "14:13:20");
assert_eq!(clock(UNIX_EPOCH), "00:00:00");
}
#[test]
fn a_cut_text_ends_with_an_ellipsis() {
assert_eq!(cut("rust_expert", 11), "rust_expert");
assert_eq!(cut("rust_expert", 20), "rust_expert");
assert_eq!(cut("rust_expert", 5), "rust…");
assert_eq!(cut("rust_expert", 1), "…");
assert_eq!(cut("rust_expert", 0), "");
}
#[test]
fn a_hanging_indent_wraps_on_words() {
assert_eq!(hang("a b c", 5, 0), ["a b c"]);
assert_eq!(hang("aaa bbb ccc", 7, 2), [" aaa", " bbb", " ccc"]);
assert_eq!(hang("aaa bbb ccc", 11, 2), [" aaa bbb", " ccc"]);
assert_eq!(hang("", 10, 2), [" "]);
assert_eq!(hang("a b", 10, 0), ["a b"], "spaces between words kept");
assert_eq!(hang("abcdefgh ij", 4, 0), ["abcdefgh", " ij"]);
}
#[test]
fn durations_show_hours_and_minutes_or_seconds() {
assert_eq!(duration(Duration::from_secs(35)), "35s");
assert_eq!(duration(Duration::from_secs(41 * 60 + 5)), "41m");
assert_eq!(duration(Duration::from_mins(62)), "1h02m");
}
}