use colored::Colorize;
use std::fmt::Display;
pub mod compression;
pub fn log_success<T: Display>(message: T) {
eprintln!("{} {}", "✓".green(), message);
}
pub fn log_info<T: Display>(message: T) {
eprintln!("{} {}", "▸".cyan(), message);
}
pub fn log_warning<T: Display>(message: T) {
eprintln!("{} {}", "⚠".yellow(), message);
}
pub fn log_error<T: Display>(message: T) {
eprintln!("{} {}", "✗".red(), message);
}
#[allow(dead_code)]
pub fn log_debug<T: Display>(message: T) {
eprintln!("{} {}", "●".dimmed(), message);
}
#[allow(dead_code)]
pub fn format_value<T: Display>(value: T, is_success: bool) -> colored::ColoredString {
if is_success {
format!("{value}").green()
} else {
format!("{value}").red()
}
}
pub fn format_jwt_token(token: &str) -> String {
let parts: Vec<&str> = token.split('.').collect();
if parts.len() < 2 {
return token.to_string();
}
if parts.len() == 2 {
return format!("{}.{}", parts[0].cyan(), parts[1]);
}
format!("{}.{}.{}", parts[0].cyan(), parts[1], parts[2].yellow())
}
pub fn start_progress_with_color(message: &str, color: &str) -> indicatif::ProgressBar {
let pb = indicatif::ProgressBar::new_spinner();
let template = format!("{{spinner:.{color}}} {{msg}}");
pb.set_style(
indicatif::ProgressStyle::default_spinner()
.template(&template)
.unwrap()
.tick_strings(&["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]),
);
pb.set_message(message.to_string());
pb.enable_steady_tick(std::time::Duration::from_millis(100));
pb
}
pub fn start_progress(message: &str) -> indicatif::ProgressBar {
start_progress_with_color(message, "blue")
}
#[allow(dead_code)]
pub fn format_duration(duration: std::time::Duration) -> String {
let seconds = duration.as_secs();
if seconds < 60 {
return format!("{seconds}s");
}
let minutes = seconds / 60;
let remain_seconds = seconds % 60;
if minutes < 60 {
return format!("{minutes}m {remain_seconds}s");
}
let hours = minutes / 60;
let remain_minutes = minutes % 60;
format!("{hours}h {remain_minutes}m {remain_seconds}s")
}
pub fn format_base64_preview(base64_str: &str) -> String {
const PREVIEW_LEN: usize = 8;
if base64_str.len() <= PREVIEW_LEN * 2 {
return base64_str.to_string();
}
let start = &base64_str[..PREVIEW_LEN];
let end = &base64_str[base64_str.len() - PREVIEW_LEN..];
let length = base64_str.len();
format!("{}...{} ({} chars)", start, end, length)
}
#[cfg(test)]
mod tests {
use super::*;
use colored::Colorize;
use std::time::Duration;
#[test]
fn test_format_jwt_token_full() {
let token = "header.payload.signature";
let expected = format!("{}.{}.{}", "header".cyan(), "payload", "signature".yellow());
assert_eq!(format_jwt_token(token), expected);
}
#[test]
fn test_format_jwt_token_no_signature() {
let token = "header.payload";
let expected = format!("{}.{}", "header".cyan(), "payload");
assert_eq!(format_jwt_token(token), expected);
}
#[test]
fn test_format_jwt_token_invalid_format() {
let token = "invalidtoken";
assert_eq!(format_jwt_token(token), "invalidtoken");
}
#[test]
fn test_format_jwt_token_empty_string() {
let token = "";
assert_eq!(format_jwt_token(token), "");
}
#[test]
fn test_format_duration_util_seconds() {
assert_eq!(format_duration(Duration::from_secs(5)), "5s");
}
#[test]
fn test_format_duration_util_minutes_seconds() {
assert_eq!(format_duration(Duration::from_secs(125)), "2m 5s");
}
#[test]
fn test_format_duration_util_hours_minutes_seconds() {
assert_eq!(format_duration(Duration::from_secs(3723)), "1h 2m 3s");
}
#[test]
fn test_format_duration_util_exact_minute() {
assert_eq!(format_duration(Duration::from_secs(60)), "1m 0s");
}
#[test]
fn test_format_duration_util_exact_hour() {
assert_eq!(format_duration(Duration::from_secs(3600)), "1h 0m 0s");
}
#[test]
fn test_format_duration_util_zero() {
assert_eq!(format_duration(Duration::ZERO), "0s");
}
#[test]
fn test_format_value_success() {
let expected = "success_text".green();
assert_eq!(format_value("success_text", true), expected);
}
#[test]
fn test_format_value_failure() {
let expected = "failure_text".red();
assert_eq!(format_value("failure_text", false), expected);
}
#[test]
fn test_format_value_integer() {
let expected = "123".green(); assert_eq!(format_value(123, true), expected);
let expected_fail = "456".red(); assert_eq!(format_value(456, false), expected_fail);
}
#[test]
fn test_format_base64_preview_empty() {
assert_eq!(format_base64_preview(""), "");
}
#[test]
fn test_format_base64_preview_short() {
let input = "SGVsbG8=";
assert_eq!(format_base64_preview(input), input);
}
#[test]
fn test_format_base64_preview_threshold() {
let input = "1234567812345678";
assert_eq!(format_base64_preview(input), input);
}
#[test]
fn test_format_base64_preview_long() {
let input = "1234567890abcdefg";
let expected = "12345678...0abcdefg (17 chars)";
assert_eq!(format_base64_preview(input), expected);
}
#[test]
fn test_format_base64_preview_very_long() {
let input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
let expected = "ABCDEFGH...456789+/ (64 chars)";
assert_eq!(format_base64_preview(input), expected);
}
}