use std::convert::Infallible;
use std::fmt;
use std::fmt::Write;
use percent_encoding::{AsciiSet, NON_ALPHANUMERIC, utf8_percent_encode};
use crate::filters::HtmlSafeOutput;
use crate::{FastWritable, Values};
const URLENCODE_STRICT_SET: &AsciiSet = &NON_ALPHANUMERIC
.remove(b'_')
.remove(b'.')
.remove(b'-')
.remove(b'~');
const URLENCODE_SET: &AsciiSet = &URLENCODE_STRICT_SET.remove(b'/');
#[inline]
pub fn urlencode<T>(s: T) -> Result<HtmlSafeOutput<UrlencodeFilter<T>>, Infallible> {
Ok(HtmlSafeOutput(UrlencodeFilter(s, URLENCODE_SET)))
}
#[inline]
pub fn urlencode_strict<T>(s: T) -> Result<HtmlSafeOutput<UrlencodeFilter<T>>, Infallible> {
Ok(HtmlSafeOutput(UrlencodeFilter(s, URLENCODE_STRICT_SET)))
}
pub struct UrlencodeFilter<T>(pub T, pub &'static AsciiSet);
impl<T: fmt::Display> fmt::Display for UrlencodeFilter<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(UrlencodeWriter(f, self.1), "{}", self.0)
}
}
impl<T: FastWritable> FastWritable for UrlencodeFilter<T> {
#[inline]
fn write_into(&self, f: &mut dyn fmt::Write, values: &dyn Values) -> crate::Result<()> {
self.0.write_into(&mut UrlencodeWriter(f, self.1), values)
}
}
struct UrlencodeWriter<W>(W, &'static AsciiSet);
impl<W: fmt::Write> fmt::Write for UrlencodeWriter<W> {
fn write_str(&mut self, s: &str) -> fmt::Result {
for s in utf8_percent_encode(s, self.1) {
self.0.write_str(s)?;
}
Ok(())
}
}
#[test]
#[cfg(feature = "alloc")]
fn test_urlencoding() {
use alloc::string::ToString;
assert_eq!(urlencode("AZaz09").unwrap().to_string(), "AZaz09");
assert_eq!(urlencode_strict("AZaz09").unwrap().to_string(), "AZaz09");
assert_eq!(urlencode("_.-~").unwrap().to_string(), "_.-~");
assert_eq!(urlencode_strict("_.-~").unwrap().to_string(), "_.-~");
assert_eq!(
urlencode(":/?#[]@").unwrap().to_string(),
"%3A/%3F%23%5B%5D%40"
);
assert_eq!(
urlencode_strict(":/?#[]@").unwrap().to_string(),
"%3A%2F%3F%23%5B%5D%40"
);
assert_eq!(
urlencode("!$&'()*+,;=").unwrap().to_string(),
"%21%24%26%27%28%29%2A%2B%2C%3B%3D"
);
assert_eq!(
urlencode_strict("!$&'()*+,;=").unwrap().to_string(),
"%21%24%26%27%28%29%2A%2B%2C%3B%3D"
);
assert_eq!(
urlencode("žŠďŤňĚáÉóŮ").unwrap().to_string(),
"%C5%BE%C5%A0%C4%8F%C5%A4%C5%88%C4%9A%C3%A1%C3%89%C3%B3%C5%AE"
);
assert_eq!(
urlencode_strict("žŠďŤňĚáÉóŮ").unwrap().to_string(),
"%C5%BE%C5%A0%C4%8F%C5%A4%C5%88%C4%9A%C3%A1%C3%89%C3%B3%C5%AE"
);
assert_eq!(urlencode("🦀").unwrap().to_string(), "%F0%9F%A6%80");
assert_eq!(urlencode_strict("🦀").unwrap().to_string(), "%F0%9F%A6%80");
}