/ src / base / kit.rs
kit.rs
 1  use tokio::signal;
 2  
 3  pub const DIRECTORY: &str = "bonfire";
 4  
 5  pub fn format_size(size: u64) -> String {
 6      const KB: u64 = 1024;
 7      const MB: u64 = KB * 1024;
 8      const GB: u64 = MB * 1024;
 9  
10      if size < KB {
11          format!("{} bytes", size)
12      } else if size < MB {
13          format!("{:.2} KB", size as f64 / KB as f64)
14      } else if size < GB {
15          format!("{:.2} MB", size as f64 / MB as f64)
16      } else {
17          format!("{:.2} GB", size as f64 / GB as f64)
18      }
19  }
20  
21  pub async fn show_usage() -> Result<(u64, u64), std::io::Error> {
22      let mut total_size = 0;
23      let mut file_count = 0;
24  
25      let mut entries = tokio::fs::read_dir(DIRECTORY).await?;
26      while let Some(entry) = entries.next_entry().await? {
27          if let Ok(metadata) = entry.metadata().await {
28              if metadata.is_file() {
29                  total_size += metadata.len();
30                  file_count += 1;
31              }
32          }
33      }
34  
35      Ok((total_size, file_count))
36  }
37  
38  pub fn get_mime_type(filename: &str) -> &'static str {
39      match std::path::Path::new(filename)
40          .extension()
41          .and_then(|e| e.to_str())
42      {
43          Some("html") | Some("htm") => "text/html",
44          Some("css") => "text/css",
45          Some("js") => "application/javascript",
46          Some("jpg") | Some("jpeg") => "image/jpeg",
47          Some("png") => "image/png",
48          Some("gif") => "image/gif",
49          Some("pdf") => "application/pdf",
50          Some("txt") => "text/plain",
51          Some("mp3") => "audio/mpeg",
52          Some("mp4") => "video/mp4",
53          Some("zip") => "application/zip",
54          _ => "application/octet-stream",
55      }
56  }
57  
58  pub fn path_is_valid(path: &str) -> bool {
59      let path = std::path::Path::new(path);
60      let mut components = path.components().peekable();
61  
62      if let Some(first) = components.peek() {
63          if !matches!(first, std::path::Component::Normal(_)) {
64              return false;
65          }
66      }
67  
68      components.count() == 1
69  }
70  
71  pub async fn shutdown_signal() {
72      let ctrl_c = async {
73          signal::ctrl_c()
74              .await
75              .expect("failed to install Ctrl+C handler");
76          tracing::info!("How dare you to trigger Ctrl+C... Adieu!");
77      };
78  
79      let terminate = async {
80          signal::unix::signal(signal::unix::SignalKind::terminate())
81              .expect("failed to install signal handler")
82              .recv()
83              .await;
84          tracing::info!("Terminated... Adieu!");
85      };
86  
87      tokio::select! {
88          _ = ctrl_c => {},
89          _ = terminate => {},
90      }
91  }