sysmonk/squire/
util.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use regex::Regex;
use std::collections::HashMap;
use std::process::Command;

/// Function to retrieve the REGEX object for an IPv4 address format
///
/// # Returns
///
/// A `Regex` object that can be used to match an IPv4 address format
pub fn ip_regex() -> Regex {
    Regex::new(
        r"^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$"
    ).unwrap()
}

/// Mapping of URLs to check for public IP addresses
///
/// # Returns
///
/// A `HashMap` containing the URL and a boolean value indicating whether the URL expects text or JSON response
pub fn public_ip_mapping() -> HashMap<String, bool> {
    let mapping: HashMap<String, bool> = vec![
        ("https://checkip.amazonaws.com/".to_string(), true), // expects text
        ("https://api.ipify.org/".to_string(), true),         // expects text
        ("https://ipinfo.io/ip/".to_string(), true),          // expects text
        ("https://v4.ident.me/".to_string(), true),           // expects text
        ("https://httpbin.org/ip".to_string(), false),        // expects JSON
        ("https://myip.dnsomatic.com/".to_string(), true),    // expects text
    ]
        .into_iter()
        .collect();
    mapping
}


/// Function to convert seconds to human-readable format
///
/// # Arguments
///
/// * `seconds` - The number of seconds to convert
///
/// # Returns
///
/// A `String` containing the human-readable format of the seconds
pub fn convert_seconds(seconds: i64) -> String {
    let days = seconds / 86_400; // 86,400 seconds in a day
    let hours = (seconds % 86_400) / 3_600; // 3,600 seconds in an hour
    let minutes = (seconds % 3_600) / 60; // 60 seconds in a minute
    let remaining_seconds = seconds % 60;

    let mut result = Vec::new();

    if days > 0 {
        result.push(format!("{} day{}", days, if days > 1 { "s" } else { "" }));
    }
    if hours > 0 {
        result.push(format!("{} hour{}", hours, if hours > 1 { "s" } else { "" }));
    }
    if minutes > 0 && result.len() < 2 {
        result.push(format!("{} minute{}", minutes, if minutes > 1 { "s" } else { "" }));
    }
    if remaining_seconds > 0 && result.len() < 2 {
        result.push(format!("{} second{}", remaining_seconds, if remaining_seconds > 1 { "s" } else { "" }));
    }
    result.join(" and ")
}

/// Function to convert byte size to human-readable format
///
/// # Arguments
///
/// * `byte_size` - The size in bytes to convert
///
/// # Returns
///
/// A `String` containing the human-readable format of the byte size
pub fn size_converter(byte_size: u64) -> String {
    let size_name = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
    let mut index = 0;
    let mut size = byte_size as f64;

    while size >= 1024.0 && index < size_name.len() - 1 {
        size /= 1024.0;
        index += 1;
    }

    format!("{:.2} {}", size, size_name[index])
}

/// Function to parse size string.
///
/// # Arguments
///
/// * `size_str` - The size string to parse
/// * `unit` - The unit to convert the size to
///
/// # Returns
///
/// A `String` containing the parsed size string.
pub fn run_command(command: &str, args: &[&str]) -> Result<String, String> {
    match Command::new(command)
        .args(args)
        .output()
    {
        Ok(output) => {
            if output.status.success() {
                Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
            } else {
                let stderr = String::from_utf8_lossy(&output.stderr).to_string();
                let exit_code = output.status.code().unwrap_or(-1);
                log::error!("Command [{}] failed with exit code: {}", command, exit_code);
                log::error!("Stderr: {}", stderr);
                Err(stderr)
            }
        }
        Err(err) => {
            log::error!("Failed to execute command: {}", err);
            Err(err.to_string())
        }
    }
}

/// Function to capitalize the first letter of each word in a string.
///
/// # Arguments
///
/// * `s` - The string to capitalize
/// * `sep` - The separator to split the string
///
/// # Returns
///
/// A `String` containing the capitalized string
pub fn capwords(string: &str, sep: Option<&str>) -> String {
    let separator = sep.unwrap_or(" ");
    let mut result = Vec::new();

    for word in string.split(separator) {
        let mut chars = word.chars();
        if let Some(first) = chars.next() {
            let capitalized_word = first.to_uppercase().collect::<String>() + chars.as_str();
            result.push(capitalized_word);
        } else {
            result.push(String::new());
        }
    }

    result.join(separator)
}