rocket_http/uri/fmt/
encoding.rs

1use std::marker::PhantomData;
2use std::borrow::Cow;
3
4use percent_encoding::AsciiSet;
5
6use crate::RawStr;
7use crate::uri::fmt::{Part, Path, Query};
8use crate::parse::uri::tables::PATH_CHARS;
9
10#[derive(Clone, Copy)]
11#[allow(non_camel_case_types)]
12pub struct UNSAFE_ENCODE_SET<P: Part>(PhantomData<P>);
13
14pub trait EncodeSet {
15    const SET: AsciiSet;
16}
17
18const fn set_from_table(table: &'static [u8; 256]) -> AsciiSet {
19    const ASCII_RANGE_LEN: u8 = 0x80;
20
21    let mut set = percent_encoding::CONTROLS.add(0);
22    let mut i: u8 = 0;
23    while i < ASCII_RANGE_LEN {
24        if table[i as usize] == 0 {
25            set = set.add(i);
26        }
27
28        i += 1;
29    }
30
31    set
32}
33
34const PATH_SET: AsciiSet = set_from_table(&PATH_CHARS);
35
36impl<P: Part> Default for UNSAFE_ENCODE_SET<P> {
37    #[inline(always)]
38    fn default() -> Self { UNSAFE_ENCODE_SET(PhantomData) }
39}
40
41impl EncodeSet for UNSAFE_ENCODE_SET<Path> {
42    const SET: AsciiSet = PATH_SET
43        .add(b'%');
44}
45
46impl EncodeSet for UNSAFE_ENCODE_SET<Query> {
47    const SET: AsciiSet = PATH_SET
48        .remove(b'?')
49        .add(b'%')
50        .add(b'+');
51}
52
53#[derive(Clone, Copy)]
54#[allow(non_camel_case_types)]
55pub struct ENCODE_SET<P: Part>(PhantomData<P>);
56
57impl EncodeSet for ENCODE_SET<Path> {
58    const SET: AsciiSet = <UNSAFE_ENCODE_SET<Path>>::SET
59        .add(b'/');
60}
61
62impl EncodeSet for ENCODE_SET<Query> {
63    const SET: AsciiSet = <UNSAFE_ENCODE_SET<Query>>::SET
64        .add(b'&')
65        .add(b'=');
66}
67
68#[derive(Default, Clone, Copy)]
69#[allow(non_camel_case_types)]
70pub struct DEFAULT_ENCODE_SET;
71
72impl EncodeSet for DEFAULT_ENCODE_SET {
73    // DEFAULT_ENCODE_SET Includes:
74    // * ENCODE_SET<Path> (and UNSAFE_ENCODE_SET<Path>)
75    const SET: AsciiSet = <ENCODE_SET<Path>>::SET
76        // * UNSAFE_ENCODE_SET<Query>
77        .add(b'%')
78        .add(b'+')
79        // * ENCODE_SET<Query>
80        .add(b'&')
81        .add(b'=');
82}
83
84pub fn percent_encode<S: EncodeSet + Default>(string: &RawStr) -> Cow<'_, str> {
85    percent_encoding::utf8_percent_encode(string.as_str(), &S::SET).into()
86}
87
88pub fn percent_encode_bytes<S: EncodeSet + Default>(bytes: &[u8]) -> Cow<'_, str> {
89    percent_encoding::percent_encode(bytes, &S::SET).into()
90}