trash_cli_core/
helpers.rs1use chrono::{DateTime, NaiveDateTime, TimeZone, Utc};
4use std::path::{Path, PathBuf};
5use std::time::{Duration, SystemTime};
6
7pub const TRASHINFO_EXTENSION: &str = ".trashinfo";
9
10pub const TRASHINFO_TIME_FORMAT: &str = "%Y-%m-%dT%H:%M:%S";
12
13pub fn sanitize_user_path(path: &Path) -> String {
15 path.display().to_string().trim().to_string()
16}
17
18pub fn build_unique_basename(file_name: &str, suffix: u64) -> String {
20 let base = Path::new(file_name)
21 .file_name()
22 .and_then(|v| v.to_str())
23 .unwrap_or("item");
24 format!("{base}.{suffix}")
25}
26
27pub fn parse_trash_datetime(value: &str) -> Option<DateTime<Utc>> {
29 NaiveDateTime::parse_from_str(value, TRASHINFO_TIME_FORMAT)
30 .ok()
31 .map(|naive| Utc.from_utc_datetime(&naive))
32 .or_else(|| DateTime::parse_from_rfc3339(value).ok().map(|dt| dt.with_timezone(&Utc)))
33}
34
35pub fn serialize_system_time(time: SystemTime) -> String {
37 let dt = DateTime::<Utc>::from(time);
38 dt.format(TRASHINFO_TIME_FORMAT).to_string()
39}
40
41pub fn print_size(bytes: u64) -> String {
43 const SUFFIXES: [&str; 5] = ["B", "K", "M", "G", "T"];
44 let mut value = bytes as f64;
45 let mut idx = 0usize;
46
47 while value >= 1024.0 && idx < SUFFIXES.len() - 1 {
48 value /= 1024.0;
49 idx += 1;
50 }
51
52 if idx == 0 {
53 format!("{:.0} {}", value, SUFFIXES[idx])
54 } else {
55 format!("{:.1} {}", value, SUFFIXES[idx])
56 }
57}
58
59pub fn canonical_or_relaxed(path: &Path) -> PathBuf {
61 path.canonicalize().unwrap_or_else(|_| path.to_path_buf())
62}
63
64pub fn format_duration(duration: Duration) -> String {
66 let secs = duration.as_secs();
67 let mins = secs / 60;
68 let hours = mins / 60;
69 let days = hours / 24;
70 let rem_secs = secs % 60;
71 let rem_mins = mins % 60;
72 let rem_hours = hours % 24;
73
74 if days > 0 {
75 format!("{days}d {rem_hours:02}:{rem_mins:02}:{rem_secs:02}")
76 } else if hours > 0 {
77 format!("{hours}h {rem_mins:02}:{rem_secs:02}")
78 } else if mins > 0 {
79 format!("{mins}m {rem_secs:02}s")
80 } else {
81 format!("{secs}s")
82 }
83}