Skip to main content

small_bin/
utils.rs

1use crate::*;
2use anyhow::Result;
3use std::{
4    fmt::Debug,
5    fs,
6    future::Future,
7    io::{self, Read, Write},
8    path::{Path, PathBuf},
9    pin::Pin,
10    time::SystemTime,
11};
12use tracing_subscriber::{EnvFilter, fmt};
13
14
15/// Initialize the instruments-subscriber
16pub fn initialize() {
17    let env_log = match EnvFilter::try_from_env("LOG") {
18        Ok(env_value_from_env) => env_value_from_env,
19        Err(_) => EnvFilter::from("info"),
20    };
21    fmt()
22        .compact()
23        .with_thread_names(false)
24        .with_thread_ids(false)
25        .with_ansi(true)
26        .with_env_filter(env_log)
27        .with_filter_reloading()
28        .init();
29}
30
31
32pub fn put_to_clipboard(text: &str) -> Result<()> {
33    let mut clipboard = clippers::Clipboard::get();
34    clipboard.write_text(text)?;
35    Ok(())
36}
37
38
39pub fn local_file_size<P: AsRef<Path>>(file_path: P) -> Result<u64> {
40    let metadata = fs::metadata(file_path)?;
41    Ok(metadata.len())
42}
43
44
45pub async fn wait_for_file<P>(path: P) -> Result<()>
46where
47    P: AsRef<Path> + Debug,
48{
49    fn check(
50        path: PathBuf,
51        last_size: u64,
52        last_mtime: Option<SystemTime>,
53        stable_intervals: u32,
54        attempts: u32,
55    ) -> Pin<Box<dyn Future<Output = Result<()>> + Send>> {
56        Box::pin(async move {
57            if attempts >= 20 {
58                warn!("File {path:?} did not stabilize after 5 seconds");
59                Ok(())
60            } else {
61                let (new_size, new_mtime) = fs::metadata(&path)
62                    .map(|m| (m.len(), m.modified().ok()))
63                    .unwrap_or((0, None));
64
65                let current_stable_intervals =
66                    if new_size > 0 && new_size == last_size && new_mtime == last_mtime {
67                        stable_intervals + 1
68                    } else {
69                        0
70                    };
71
72                if current_stable_intervals >= 2 {
73                    debug!("File {:?} is stable after {}ms", path, attempts * 250);
74                    Ok(())
75                } else {
76                    tokio::time::sleep(std::time::Duration::from_millis(250)).await;
77                    check(
78                        path,
79                        new_size,
80                        new_mtime,
81                        current_stable_intervals,
82                        attempts + 1,
83                    )
84                    .await
85                }
86            }
87        })
88    }
89
90    check(path.as_ref().to_path_buf(), 0, None, 0, 0).await
91}
92
93
94pub fn size_kib(size_in_bytes: u64) -> f64 {
95    (size_in_bytes as f64) / 1024.0
96}
97
98
99pub fn file_extension<P: AsRef<Path>>(path: P) -> String {
100    path.as_ref()
101        .extension()
102        .and_then(|e| e.to_str())
103        .map(|e| format!(".{e}"))
104        .unwrap_or_default()
105}
106
107
108pub fn stream_file_to_remote<R, W>(
109    reader: &mut R,
110    writer: &mut W,
111    buffer_size: usize,
112    total_size: u64,
113) -> Result<()>
114where
115    R: Read,
116    W: Write,
117{
118    let mut buffer = vec![0u8; buffer_size];
119    // let mut bytes_written = 0u64;
120    let chunks = if total_size > 0 {
121        (total_size / buffer_size as u64) + 1
122    } else {
123        1
124    };
125
126    info!(
127        "Streaming file of size: {:.2}KiB to remote server..",
128        size_kib(total_size)
129    );
130
131    let mut chunk_index = 0u64;
132    loop {
133        let bytes_read = reader.read(&mut buffer)?;
134        if bytes_read == 0 {
135            break;
136        }
137
138        writer.write_all(&buffer[..bytes_read])?;
139        chunk_index += 1;
140
141        let percent = if chunks > 0 {
142            (chunk_index as f64 * 100.0) / chunks as f64
143        } else {
144            100.0
145        };
146
147        eprint!("\rProgress: {percent:.2}% ");
148        io::stderr().flush()?;
149    }
150
151    eprintln!(); // New line after progress
152    info!("Upload complete!");
153    Ok(())
154}