use percent_encoding::{percent_decode, utf8_percent_encode, AsciiSet, NON_ALPHANUMERIC};
use std::path::{Path, PathBuf};
pub const PERCENT_ENCODE_SET: &AsciiSet = &NON_ALPHANUMERIC
.remove(b'-')
.remove(b'_')
.remove(b'.')
.remove(b'~');
pub fn encode_uri(file_path: &Path) -> String {
assert!(!file_path.is_absolute());
file_path
.iter()
.flat_map(|component| {
let component = component.to_str().unwrap();
let segment = utf8_percent_encode(component, PERCENT_ENCODE_SET);
std::iter::once("/").chain(segment)
})
.collect::<String>()
}
pub fn decode_uri(file_path: &str) -> PathBuf {
file_path
.split('/')
.map(|encoded_part| {
let decode = percent_decode(encoded_part.as_bytes());
let decode = decode.decode_utf8_lossy();
decode.to_string()
})
.collect::<PathBuf>()
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use std::str::FromStr;
use super::{decode_uri, encode_uri};
#[test]
fn encodes_uri() {
let file_path = "/these are important files/do_not_delete/file name.txt";
let file_path = PathBuf::from_str(file_path).unwrap();
let file_path = encode_uri(&file_path);
assert_eq!(
file_path,
"/these%20are%20important%20files/do_not_delete/file%20name.txt"
);
}
#[test]
fn decodes_uri() {
let file_path = "these%20are%20important%20files/do_not_delete/file%20name.txt";
let file_path = decode_uri(file_path);
let file_path = file_path.to_str().unwrap();
assert_eq!(
file_path,
"these are important files/do_not_delete/file name.txt"
);
}
}