1use colored::Colorize;
2use std::fmt::Display;
3
4pub mod compression;
5
6pub fn log_success<T: Display>(message: T) {
8 println!("{} {}", "[+]".bright_green(), message);
9}
10
11pub fn log_info<T: Display>(message: T) {
13 println!("{} {}", "[*]".bright_blue(), message);
14}
15
16pub fn log_warning<T: Display>(message: T) {
18 println!("{} {}", "[!]".yellow(), message);
19}
20
21pub fn log_error<T: Display>(message: T) {
23 println!("{} {}", "[-]".bright_red(), message);
24}
25
26#[allow(dead_code)]
28pub fn log_debug<T: Display>(message: T) {
29 println!("{} {}", "[?]".cyan(), message);
30}
31
32#[allow(dead_code)]
34pub fn format_value<T: Display>(value: T, is_success: bool) -> colored::ColoredString {
35 if is_success {
36 format!("{value}").bright_green()
37 } else {
38 format!("{value}").bright_red()
39 }
40}
41
42pub fn format_jwt_token(token: &str) -> String {
44 let parts: Vec<&str> = token.split('.').collect();
45
46 if parts.len() < 2 {
47 return token.to_string();
48 }
49
50 if parts.len() == 2 {
51 return format!("{}.{}", parts[0].bright_blue(), parts[1].bright_magenta());
53 }
54
55 format!(
57 "{}.{}.{}",
58 parts[0].bright_blue(),
59 parts[1].bright_magenta(),
60 parts[2].bright_yellow()
61 )
62}
63
64pub fn start_progress(message: &str) -> indicatif::ProgressBar {
66 let pb = indicatif::ProgressBar::new_spinner();
67 pb.set_style(
68 indicatif::ProgressStyle::default_spinner()
69 .template("{spinner:.blue} {msg}")
70 .unwrap()
71 .tick_strings(&["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]),
72 );
73 pb.set_message(message.to_string());
74 pb.enable_steady_tick(std::time::Duration::from_millis(100));
75 pb
76}
77
78#[allow(dead_code)]
80pub fn format_duration(duration: std::time::Duration) -> String {
81 let seconds = duration.as_secs();
82
83 if seconds < 60 {
84 return format!("{seconds}s");
85 }
86
87 let minutes = seconds / 60;
88 let remain_seconds = seconds % 60;
89
90 if minutes < 60 {
91 return format!("{minutes}m {remain_seconds}s");
92 }
93
94 let hours = minutes / 60;
95 let remain_minutes = minutes % 60;
96
97 format!("{hours}h {remain_minutes}m {remain_seconds}s")
98}
99
100pub fn format_base64_preview(base64_str: &str) -> String {
102 const PREVIEW_LEN: usize = 8;
103
104 if base64_str.len() <= PREVIEW_LEN * 2 {
105 return base64_str.to_string();
106 }
107
108 let start = &base64_str[..PREVIEW_LEN];
109 let end = &base64_str[base64_str.len() - PREVIEW_LEN..];
110 let length = base64_str.len();
111
112 format!("{}...{} ({} chars)", start, end, length)
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118 use colored::Colorize;
119 use std::time::Duration;
120
121 #[test]
122 fn test_format_jwt_token_full() {
123 let token = "header.payload.signature";
124 let expected = format!(
125 "{}.{}.{}",
126 "header".bright_blue(),
127 "payload".bright_magenta(),
128 "signature".bright_yellow()
129 );
130 assert_eq!(format_jwt_token(token), expected);
131 }
132
133 #[test]
134 fn test_format_jwt_token_no_signature() {
135 let token = "header.payload";
136 let expected = format!("{}.{}", "header".bright_blue(), "payload".bright_magenta());
137 assert_eq!(format_jwt_token(token), expected);
138 }
139
140 #[test]
141 fn test_format_jwt_token_invalid_format() {
142 let token = "invalidtoken";
143 assert_eq!(format_jwt_token(token), "invalidtoken");
144 }
145
146 #[test]
147 fn test_format_jwt_token_empty_string() {
148 let token = "";
149 assert_eq!(format_jwt_token(token), "");
150 }
151
152 #[test]
153 fn test_format_duration_util_seconds() {
154 assert_eq!(format_duration(Duration::from_secs(5)), "5s");
155 }
156
157 #[test]
158 fn test_format_duration_util_minutes_seconds() {
159 assert_eq!(format_duration(Duration::from_secs(125)), "2m 5s");
160 }
161
162 #[test]
163 fn test_format_duration_util_hours_minutes_seconds() {
164 assert_eq!(format_duration(Duration::from_secs(3723)), "1h 2m 3s");
165 }
166
167 #[test]
168 fn test_format_duration_util_exact_minute() {
169 assert_eq!(format_duration(Duration::from_secs(60)), "1m 0s");
170 }
171
172 #[test]
173 fn test_format_duration_util_exact_hour() {
174 assert_eq!(format_duration(Duration::from_secs(3600)), "1h 0m 0s");
175 }
176
177 #[test]
178 fn test_format_duration_util_zero() {
179 assert_eq!(format_duration(Duration::ZERO), "0s");
180 }
181
182 #[test]
183 fn test_format_value_success() {
184 let expected = "success_text".bright_green();
185 assert_eq!(format_value("success_text", true), expected);
186 }
187
188 #[test]
189 fn test_format_value_failure() {
190 let expected = "failure_text".bright_red();
191 assert_eq!(format_value("failure_text", false), expected);
192 }
193
194 #[test]
195 fn test_format_value_integer() {
196 let expected = "123".bright_green(); assert_eq!(format_value(123, true), expected);
198
199 let expected_fail = "456".bright_red(); assert_eq!(format_value(456, false), expected_fail);
201 }
202}