#[must_use]
pub fn js_encode_uri_component(s: &str) -> String {
encoded(s, kept_by_encode_uri_component)
}
#[must_use]
pub fn js_encode_uri(s: &str) -> String {
encoded(s, kept_by_encode_uri)
}
fn encoded(s: &str, keep: fn(char) -> bool) -> String {
let mut out = String::with_capacity(s.len());
for c in s.chars() {
if keep(c) {
out.push(c);
} else {
percent_encode_into(&mut out, c);
}
}
out
}
fn kept_by_encode_uri_component(c: char) -> bool {
c.is_ascii_alphanumeric() || matches!(c, '-' | '_' | '.' | '!' | '~' | '*' | '\'' | '(' | ')')
}
#[doc(hidden)]
#[must_use]
pub fn kept_by_encode_uri(c: char) -> bool {
kept_by_encode_uri_component(c)
|| matches!(
c,
';' | '/' | '?' | ':' | '@' | '&' | '=' | '+' | '$' | ',' | '#'
)
}
#[doc(hidden)]
pub fn percent_encode_into(out: &mut String, c: char) {
const HEX: &[u8; 16] = b"0123456789ABCDEF";
let mut buf = [0; 4];
for &b in c.encode_utf8(&mut buf).as_bytes() {
out.push('%');
out.push(char::from(HEX[usize::from(b >> 4)]));
out.push(char::from(HEX[usize::from(b & 0xF)]));
}
}
#[cfg(test)]
mod tests;