use std::borrow::Cow;
use std::fmt::Write;
const NON_ASCII_CHARACTER_THRESHOLD: u32 = 128;
#[inline]
fn is_slugify2_symbol(c: char) -> bool {
matches!(
c,
'\t' | ' '
| '!'
| '"'
| '#'
| '$'
| '%'
| '&'
| '\''
| '('
| ')'
| '*'
| '-'
| '/'
| '<'
| '='
| '>'
| '?'
| '@'
| '['
| '\\'
| ']'
| '^'
| '_'
| '`'
| '{'
| '|'
| '}'
| ','
| '.'
| ':'
)
}
pub fn slugify2(nickname: &str) -> Cow<'_, str> {
let needs_processing = nickname
.chars()
.any(|c| is_slugify2_symbol(c) || (c as u32) >= NON_ASCII_CHARACTER_THRESHOLD);
if !needs_processing {
return Cow::Borrowed(nickname);
}
let mut result = String::with_capacity(nickname.len() * 4);
for c in nickname.chars() {
if is_slugify2_symbol(c) || (c as u32) >= NON_ASCII_CHARACTER_THRESHOLD {
write!(&mut result, "-{}-", c as u32).unwrap();
} else {
result.push(c);
}
}
Cow::Owned(result)
}
pub fn encode(nickname: &str) -> Cow<'_, str> {
if nickname
.bytes()
.all(|b| b.is_ascii_alphanumeric() || matches!(b, b'-' | b'_' | b'.' | b'~'))
{
return Cow::Borrowed(nickname);
}
let mut out = String::with_capacity(nickname.len() * 3);
for &b in nickname.as_bytes() {
if b.is_ascii_alphanumeric() || matches!(b, b'-' | b'_' | b'.' | b'~') {
out.push(b as char);
} else {
out.push('%');
out.push(hex_upper(b >> 4));
out.push(hex_upper(b & 0x0f));
}
}
Cow::Owned(out)
}
#[inline]
fn hex_upper(n: u8) -> char {
debug_assert!(n < 16);
match n {
0..=9 => (b'0' + n) as char,
10..=15 => (b'A' + (n - 10)) as char,
_ => unreachable!(),
}
}