url_utils/
encode.rs

1use crate::Result;
2use std::borrow::Cow;
3
4/// UrlEncode the given string
5pub fn encode(url: &str) -> Result<Cow<str>> {
6    let is_ascii = |c: &u8|
7                    matches!(c, b'0'..=b'9' | b'A'..=b'Z' |
8                                b'a'..=b'z' | b'-' | b'.' |
9                                b'_' | b'~');
10    let len = url.as_bytes()
11                 .iter()
12                 .take_while(|c| is_ascii(*c)).count();
13    if len >= url.len() {
14        return Ok(url.into());
15    }
16    let mut buf = String::new();
17    for byte in url.as_bytes() {
18        if is_ascii(byte) {
19            buf.push(*byte as char);
20        } else {
21            buf.push('%');
22            buf.push(to_hex_digit(byte >> 4));
23            buf.push(to_hex_digit(byte & 0b1111));
24        }
25    }
26    Ok(buf.into())
27}
28
29#[inline(always)]
30fn to_hex_digit(digit: u8) -> char {
31    (match digit {
32        0..=9 => b'0' + digit,
33        10..=255 => b'A' - 10 + digit,
34    } as char)
35}