///|
/// Percent-encodes UTF-8 bytes, preserving only RFC 3986 unreserved bytes.
pub fn percent_encode(value : String) -> String {
encode_url_bytes(value, false)
}
///|
/// Percent-encodes a multi-segment path, also preserving slash separators.
pub fn percent_encode_path(value : String) -> String {
encode_url_bytes(value, true)
}
///|
fn encode_url_bytes(value : String, keep_slash : Bool) -> String {
let hex = b"0123456789ABCDEF"
let output : Array[Byte] = []
for byte in @utf8.encode(value) {
let code = byte.to_int()
if (code >= 65 && code <= 90) ||
(code >= 97 && code <= 122) ||
(code >= 48 && code <= 57) ||
byte == b'-' ||
byte == b'.' ||
byte == b'_' ||
byte == b'~' ||
(keep_slash && byte == b'/') {
output.push(byte)
} else {
output.push(b'%')
output.push(hex[code >> 4])
output.push(hex[code & 15])
}
}
try! @utf8.decode(Bytes::from_array(output))
}
///|
/// Appends an encoded query pair, using ampersand if the URL contains `?`.
pub fn append_query(url : String, name : String, value : String) -> String {
let separator = if url.contains("?") { "&" } else { "?" }
url + separator + percent_encode(name) + "=" + percent_encode(value)
}