aws_smithy_http/
label.rs

1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6//! Formatting values as Smithy
7//! [httpLabel](https://smithy.io/2.0/spec/http-bindings.html#httplabel-trait)
8
9use crate::urlencode::BASE_SET;
10use aws_smithy_types::date_time::{DateTimeFormatError, Format};
11use aws_smithy_types::DateTime;
12use percent_encoding::AsciiSet;
13
14const GREEDY: &AsciiSet = &BASE_SET.remove(b'/');
15
16/// The encoding strategy used when parsing an `httpLabel`.
17#[non_exhaustive]
18#[derive(Clone, Debug, Eq, PartialEq)]
19pub enum EncodingStrategy {
20    /// The default strategy when parsing an `httpLabel`. Only one path segment will be matched.
21    Default,
22    /// When parsing an `httpLabel`, this strategy will attempt to parse as many path segments as possible.
23    Greedy,
24}
25
26/// Format a given `httpLabel` as a string according to an [`EncodingStrategy`]
27pub fn fmt_string<T: AsRef<str>>(t: T, strategy: EncodingStrategy) -> String {
28    let uri_set = if strategy == EncodingStrategy::Greedy {
29        GREEDY
30    } else {
31        BASE_SET
32    };
33    percent_encoding::utf8_percent_encode(t.as_ref(), uri_set).to_string()
34}
35
36/// Format a given [`DateTime`] as a string according to an [`EncodingStrategy`]
37pub fn fmt_timestamp(t: &DateTime, format: Format) -> Result<String, DateTimeFormatError> {
38    Ok(fmt_string(t.fmt(format)?, EncodingStrategy::Default))
39}
40
41#[cfg(test)]
42mod test {
43    use crate::label::{fmt_string, EncodingStrategy};
44    use http_02x::Uri;
45    use proptest::proptest;
46
47    #[test]
48    fn greedy_params() {
49        assert_eq!(fmt_string("a/b", EncodingStrategy::Default), "a%2Fb");
50        assert_eq!(fmt_string("a/b", EncodingStrategy::Greedy), "a/b");
51    }
52
53    proptest! {
54        #[test]
55        fn test_encode_request(s: String) {
56            let _: Uri = format!("http://host.example.com/{}", fmt_string(&s, EncodingStrategy::Default))
57                .parse()
58                .expect("all strings should be encoded properly");
59            let _: Uri = format!("http://host.example.com/{}", fmt_string(&s, EncodingStrategy::Greedy))
60                .parse()
61                .expect("all strings should be encoded properly");
62        }
63    }
64}