aws_smithy_http/
query.rs
1use crate::urlencode::BASE_SET;
12use aws_smithy_types::date_time::{DateTimeFormatError, Format};
13use aws_smithy_types::DateTime;
14use percent_encoding::utf8_percent_encode;
15
16pub fn fmt_string<T: AsRef<str>>(t: T) -> String {
18 utf8_percent_encode(t.as_ref(), BASE_SET).to_string()
19}
20
21pub fn fmt_timestamp(t: &DateTime, format: Format) -> Result<String, DateTimeFormatError> {
23 Ok(fmt_string(t.fmt(format)?))
24}
25
26#[allow(missing_debug_implementations)]
37pub struct Writer<'a> {
38 out: &'a mut String,
39 prefix: char,
40}
41
42impl<'a> Writer<'a> {
43 pub fn new(out: &'a mut String) -> Self {
45 Writer { out, prefix: '?' }
46 }
47
48 pub fn push_kv(&mut self, k: &str, v: &str) {
50 self.out.push(self.prefix);
51 self.out.push_str(k);
52 self.out.push('=');
53 self.out.push_str(v);
54 self.prefix = '&';
55 }
56
57 pub fn push_v(&mut self, v: &str) {
59 self.out.push(self.prefix);
60 self.out.push_str(v);
61 self.prefix = '&';
62 }
63}
64
65#[cfg(test)]
66mod test {
67 use crate::query::{fmt_string, Writer};
68 use http_02x::Uri;
69 use proptest::proptest;
70
71 #[test]
72 fn url_encode() {
73 assert_eq!(fmt_string("y̆").as_str(), "y%CC%86");
74 assert_eq!(fmt_string(" ").as_str(), "%20");
75 assert_eq!(fmt_string("foo/baz%20").as_str(), "foo%2Fbaz%2520");
76 assert_eq!(fmt_string("&=").as_str(), "%26%3D");
77 assert_eq!(fmt_string("🐱").as_str(), "%F0%9F%90%B1");
78 assert_eq!(fmt_string("a:b"), "a%3Ab")
80 }
81
82 #[test]
83 fn writer_sets_prefix_properly() {
84 let mut out = String::new();
85 let mut writer = Writer::new(&mut out);
86 writer.push_v("a");
87 writer.push_kv("b", "c");
88 assert_eq!(out, "?a&b=c");
89 }
90
91 proptest! {
92 #[test]
93 fn test_encode_request(s: String) {
94 let _: Uri = format!("http://host.example.com/?{}", fmt_string(s)).parse().expect("all strings should be encoded properly");
95 }
96 }
97}