1use percent_encoding::{AsciiSet, NON_ALPHANUMERIC, percent_encode};
2use plf::{Kwargs, State};
3
4const FRAGMENT_ENCODE_SET: &AsciiSet = &percent_encoding::CONTROLS
6 .add(b' ')
7 .add(b'"')
8 .add(b'<')
9 .add(b'>')
10 .add(b'`');
11
12const PATH_ENCODE_SET: &AsciiSet = &FRAGMENT_ENCODE_SET.add(b'#').add(b'?').add(b'{').add(b'}');
14
15const USERINFO_ENCODE_SET: &AsciiSet = &PATH_ENCODE_SET
17 .add(b'/')
18 .add(b':')
19 .add(b';')
20 .add(b'=')
21 .add(b'@')
22 .add(b'[')
23 .add(b'\\')
24 .add(b']')
25 .add(b'^')
26 .add(b'|');
27
28const PYTHON_ENCODE_SET: &AsciiSet = &USERINFO_ENCODE_SET
32 .remove(b'/')
33 .add(b'%')
34 .add(b':')
35 .add(b'?')
36 .add(b'#')
37 .add(b'[')
38 .add(b']')
39 .add(b'@')
40 .add(b'!')
41 .add(b'$')
42 .add(b'&')
43 .add(b'\'')
44 .add(b'(')
45 .add(b')')
46 .add(b'*')
47 .add(b'+')
48 .add(b',')
49 .add(b';')
50 .add(b'=');
51
52pub fn urlencode(val: &str, _: Kwargs, _: &State) -> String {
59 percent_encode(val.as_bytes(), PYTHON_ENCODE_SET).to_string()
60}
61
62pub fn urlencode_strict(val: &str, _: Kwargs, _: &State) -> String {
69 percent_encode(val.as_bytes(), NON_ALPHANUMERIC).to_string()
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75 use plf::{Context, Kwargs, State};
76
77 #[test]
78 fn test_urlencode() {
79 let ctx = Context::new();
80 let state = State::new(&ctx);
81 assert_eq!(
82 urlencode("hello world", Kwargs::default(), &state),
83 "hello%20world"
84 );
85 assert_eq!(
86 urlencode("foo/bar?baz=1", Kwargs::default(), &state),
87 "foo/bar%3Fbaz%3D1"
88 );
89 }
90
91 #[test]
92 fn test_urlencode_strict() {
93 let ctx = Context::new();
94 let state = State::new(&ctx);
95 assert_eq!(
96 urlencode_strict("hello", Kwargs::default(), &state),
97 "hello"
98 );
99 assert_eq!(urlencode_strict("a/b", Kwargs::default(), &state), "a%2Fb");
100 }
101
102 #[test]
103 fn test_register() {
104 let mut tera = plf::Tera::default();
105 tera.register_filter("urlencode", urlencode);
106 tera.register_filter("urlencode_strict", urlencode_strict);
107 }
108}