1use super::Encoder;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum UriReserved {
9 Any,
10 Path,
11 Query,
12 Fragment,
13}
14
15impl UriReserved {
16 fn is_reserved_but_safe(&self, c: char) -> bool {
17 match self {
18 Self::Any => false,
19 Self::Path => is_sub_delim(c) || c == '@',
20 Self::Query | Self::Fragment => is_sub_delim(c) || matches!(c, ':' | '@' | '/' | '?'),
21 }
22 }
23}
24
25impl Encoder for UriReserved {
26 fn encode(&self, c: char) -> bool {
27 !is_unreserved(c) && !self.is_reserved_but_safe(c)
28 }
29}
30
31fn is_sub_delim(c: char) -> bool {
32 matches!(
33 c,
34 '!' | '$' | '&' | '\'' | '(' | ')' | '*' | '+' | ',' | ';' | '='
35 )
36}
37
38fn is_unreserved(c: char) -> bool {
39 c.is_ascii_alphanumeric() || matches!(c, '-' | '.' | '_' | '~')
40}
41
42#[cfg(test)]
43mod tests {
44 use crate::PctString;
45
46 use super::UriReserved;
47
48 #[test]
49 fn uri_encode_cyrillic() {
50 let encoder = UriReserved::Any;
51 let pct_string = PctString::encode("традиционное польское блюдо\0".chars(), encoder);
52 assert_eq!(&pct_string, &"традиционное польское блюдо\0");
53 assert_eq!(
54 &pct_string.as_str(),
55 &"%D1%82%D1%80%D0%B0%D0%B4%D0%B8%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D0%BE%D0%B5%20%D0%BF%D0%BE%D0%BB%D1%8C%D1%81%D0%BA%D0%BE%D0%B5%20%D0%B1%D0%BB%D1%8E%D0%B4%D0%BE%00"
56 );
57 }
58}