1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use std::marker::PhantomData;
use std::borrow::Cow;

use percent_encoding::{EncodeSet, utf8_percent_encode};

use uri::{UriPart, Path, Query};
use parse::uri::is_pchar;

#[derive(Clone, Copy)]
#[allow(non_camel_case_types)]
crate struct UNSAFE_ENCODE_SET<P: UriPart>(PhantomData<P>);

impl<P: UriPart> Default for UNSAFE_ENCODE_SET<P> {
    #[inline(always)]
    fn default() -> Self { UNSAFE_ENCODE_SET(PhantomData) }
}

impl EncodeSet for UNSAFE_ENCODE_SET<Path> {
    #[inline(always)]
    fn contains(&self, byte: u8) -> bool {
        !is_pchar(byte) || byte == b'%'
    }
}

impl EncodeSet for UNSAFE_ENCODE_SET<Query> {
    #[inline(always)]
    fn contains(&self, byte: u8) -> bool {
        (!is_pchar(byte) && (byte != b'?')) || byte == b'%' || byte == b'+'
    }
}

#[derive(Clone, Copy)]
#[allow(non_camel_case_types)]
crate struct ENCODE_SET<P: UriPart>(PhantomData<P>);

impl EncodeSet for ENCODE_SET<Path> {
    #[inline(always)]
    fn contains(&self, byte: u8) -> bool {
        <UNSAFE_ENCODE_SET<Path>>::default().contains(byte) || byte == b'/'
    }
}

impl EncodeSet for ENCODE_SET<Query> {
    #[inline(always)]
    fn contains(&self, byte: u8) -> bool {
        <UNSAFE_ENCODE_SET<Query>>::default().contains(byte) || match byte {
            b'&' | b'=' => true,
            _ => false
        }
    }
}

#[derive(Default, Clone, Copy)]
#[allow(non_camel_case_types)]
crate struct DEFAULT_ENCODE_SET;

impl EncodeSet for DEFAULT_ENCODE_SET {
    #[inline(always)]
    fn contains(&self, byte: u8) -> bool {
        ENCODE_SET::<Path>(PhantomData).contains(byte) ||
            ENCODE_SET::<Query>(PhantomData).contains(byte)
    }
}

crate fn unsafe_percent_encode<P: UriPart>(string: &str) -> Cow<str> {
    match P::DELIMITER {
        '/' => percent_encode::<UNSAFE_ENCODE_SET<Path>>(string),
        '&' => percent_encode::<UNSAFE_ENCODE_SET<Query>>(string),
        _ => percent_encode::<DEFAULT_ENCODE_SET>(string)
    }
}

crate fn percent_encode<S: EncodeSet + Default>(string: &str) -> Cow<str> {
    utf8_percent_encode(string, S::default()).into()
}