pub fn capitalize(s: &str) -> String {
let mut chars = s.chars();
match chars.next() {
Some(c) => c.to_uppercase().collect::<String>() + chars.as_str(),
None => String::new(),
}
}
pub fn progress_bar(done: u64, total: u64, width: usize) -> String {
let width = width.max(1);
let total = total.max(1);
let filled = ((done as f64 / total as f64) * width as f64).round() as usize;
let filled = filled.min(width);
let empty = width - filled;
let mut s = String::with_capacity(width * 3);
s.push_str(&"\u{25B0}".repeat(filled));
s.push_str(&"\u{25B1}".repeat(empty));
s
}
pub fn urlencode(s: &str) -> String {
let mut out = String::with_capacity(s.len());
for byte in s.as_bytes() {
match byte {
b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
out.push(*byte as char);
}
_ => out.push_str(&format!("%{:02X}", byte)),
}
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn capitalize_ascii() {
assert_eq!(capitalize("telegram"), "Telegram");
assert_eq!(capitalize(""), "");
}
#[test]
fn capitalize_unicode() {
assert_eq!(capitalize("ёлка"), "Ёлка");
}
#[test]
fn progress_bar_edges() {
assert_eq!(progress_bar(0, 10, 4), "▱▱▱▱");
assert_eq!(progress_bar(10, 10, 4), "▰▰▰▰");
assert_eq!(progress_bar(5, 0, 4), "▰▰▰▰"); }
#[test]
fn urlencode_basic() {
assert_eq!(urlencode("hello"), "hello");
assert_eq!(urlencode("hello world"), "hello%20world");
assert_eq!(urlencode("a&b=c"), "a%26b%3Dc");
}
}