Skip to main content

ephemeris_forge/
segment.rs

1use percent_encoding::{AsciiSet, CONTROLS, NON_ALPHANUMERIC, utf8_percent_encode};
2
3/// The set `url` itself percent-encodes a path segment with, plus the
4/// characters that would end or split one.
5const PATH_SEGMENT: &AsciiSet = &CONTROLS
6    .add(b' ')
7    .add(b'"')
8    .add(b'<')
9    .add(b'>')
10    .add(b'`')
11    .add(b'#')
12    .add(b'?')
13    .add(b'{')
14    .add(b'}')
15    .add(b'%')
16    .add(b'/');
17
18const QUERY_VALUE: &AsciiSet = &NON_ALPHANUMERIC
19    .remove(b'-')
20    .remove(b'.')
21    .remove(b'_')
22    .remove(b'~');
23
24/// Percent-encode `value` for use as one segment of a request path.
25///
26/// A name such as `area/docs` stays one segment as `area%2Fdocs`.
27#[must_use]
28pub fn path_segment(value: &str) -> String {
29    utf8_percent_encode(value, PATH_SEGMENT).to_string()
30}
31
32/// Percent-encode `value` for use as a query parameter value.
33#[must_use]
34pub fn query_value(value: &str) -> String {
35    utf8_percent_encode(value, QUERY_VALUE).to_string()
36}
37
38#[cfg(test)]
39mod tests {
40    use super::{path_segment, query_value};
41
42    #[test]
43    fn query_delimiters_are_encoded() {
44        assert_eq!(query_value("a+b&c#d e/f"), "a%2Bb%26c%23d%20e%2Ff");
45    }
46
47    #[test]
48    fn separators_and_spaces_are_encoded() {
49        assert_eq!(
50            path_segment("area/docs & more?"),
51            "area%2Fdocs%20&%20more%3F"
52        );
53        assert_eq!(path_segment("plain-name_1"), "plain-name_1");
54    }
55}