rebuilderd_common/
utils.rs1use crate::errors::*;
2use std::fs::{self, OpenOptions};
3use std::io::prelude::*;
4use std::os::unix::fs::OpenOptionsExt;
5use std::path::Path;
6
7pub fn secs_to_human(duration: i64) -> String {
8 let secs = duration % 60;
9 let mins = duration / 60;
10 let hours = mins / 60;
11 let mins = mins % 60;
12
13 let mut out = Vec::new();
14 if hours > 0 {
15 out.push(format!("{:2}h", hours));
16 }
17 if mins > 0 || hours > 0 {
18 out.push(format!("{:2}m", mins));
19 }
20 out.push(format!("{:2}s", secs));
21
22 out.join(" ")
23}
24
25pub fn load_or_create<F: Fn() -> Result<Vec<u8>>>(path: &Path, func: F) -> Result<Vec<u8>> {
26 let data = match OpenOptions::new()
27 .mode(0o640)
28 .write(true)
29 .create_new(true)
30 .open(path)
31 {
32 Ok(mut file) => {
33 let data = func()?;
35 file.write_all(&data[..])?;
36 data
37 }
38 Err(_err) => {
39 debug!("Loading data from file: {path:?}");
41 fs::read(path)?
42 }
43 };
44
45 Ok(data)
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn test_secs_to_human_0s() {
54 let x = secs_to_human(0);
55 assert_eq!(x, " 0s");
56 }
57
58 #[test]
59 fn test_secs_to_human_1s() {
60 let x = secs_to_human(1);
61 assert_eq!(x, " 1s");
62 }
63
64 #[test]
65 fn test_secs_to_human_1m() {
66 let x = secs_to_human(60);
67 assert_eq!(x, " 1m 0s");
68 }
69
70 #[test]
71 fn test_secs_to_human_1m_30s() {
72 let x = secs_to_human(90);
73 assert_eq!(x, " 1m 30s");
74 }
75
76 #[test]
77 fn test_secs_to_human_10m_30s() {
78 let x = secs_to_human(630);
79 assert_eq!(x, "10m 30s");
80 }
81
82 #[test]
83 fn test_secs_to_human_1h() {
84 let x = secs_to_human(3600);
85 assert_eq!(x, " 1h 0m 0s");
86 }
87
88 #[test]
89 fn test_secs_to_human_12h_10m_30s() {
90 let x = secs_to_human(3600 * 12 + 600 + 30);
91 assert_eq!(x, "12h 10m 30s");
92 }
93
94 #[test]
95 fn test_secs_to_human_100h() {
96 let x = secs_to_human(3600 * 100);
97 assert_eq!(x, "100h 0m 0s");
98 }
99}