use crate::{Transform, TransformError, TransformerCategory};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct UrlEncode;
impl Transform for UrlEncode {
fn name(&self) -> &'static str {
"URL Encode"
}
fn id(&self) -> &'static str {
"urlencode"
}
fn description(&self) -> &'static str {
"Encode text for use in URLs"
}
fn category(&self) -> TransformerCategory {
TransformerCategory::Encoder
}
fn transform(&self, input: &str) -> Result<String, TransformError> {
let mut encoded = String::new();
for byte in input.bytes() {
match byte {
b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' => encoded.push(byte as char),
b'-' | b'_' | b'.' | b'~' => encoded.push(byte as char),
b' ' => encoded.push('+'),
_ => {
encoded.push('%');
encoded.push_str(&format!("{:02X}", byte));
}
}
}
Ok(encoded)
}
fn default_test_input(&self) -> &'static str {
"Hello, World! This is a test + example?"
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_url_encode() {
let transformer = UrlEncode;
assert_eq!(
transformer
.transform(transformer.default_test_input())
.unwrap(),
"Hello%2C+World%21+This+is+a+test+%2B+example%3F"
);
assert_eq!(transformer.transform("a b").unwrap(), "a+b");
assert_eq!(transformer.transform("100%").unwrap(), "100%25");
}
}