twilight_http/
query_formatter.rs1use std::fmt::{Display, Formatter, Write};
2
3pub struct QueryStringFormatter<'w1, 'w2> {
5 formatter: &'w1 mut Formatter<'w2>,
6 is_first: bool,
7}
8
9impl<'w1, 'w2> QueryStringFormatter<'w1, 'w2> {
10 pub fn new(formatter: &'w1 mut Formatter<'w2>) -> Self {
11 Self {
12 formatter,
13 is_first: true,
14 }
15 }
16
17 pub fn write_param(&mut self, key: &str, value: &impl Display) -> std::fmt::Result {
23 if self.is_first {
24 self.formatter.write_char('?')?;
25 self.is_first = false;
26 } else {
27 self.formatter.write_char('&')?;
28 }
29
30 self.formatter.write_str(key)?;
31 self.formatter.write_char('=')?;
32 Display::fmt(value, self.formatter)
33 }
34
35 pub fn write_opt_param(&mut self, key: &str, value: Option<&impl Display>) -> std::fmt::Result {
41 if let Some(value) = value {
42 self.write_param(key, value)
43 } else {
44 Ok(())
45 }
46 }
47}
48
49#[derive(Debug)]
52pub struct QueryArray<T>(pub T);
53
54impl<T, U> Display for QueryArray<T>
55where
56 T: IntoIterator<Item = U> + Clone,
57 U: Display,
58{
59 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60 let mut iter = self.0.clone().into_iter().peekable();
61
62 while let Some(item) = iter.next() {
63 Display::fmt(&item, f)?;
64 if iter.peek().is_some() {
65 f.write_str(",")?;
66 }
67 }
68
69 Ok(())
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 struct Test {
78 a: Option<u32>,
79 b: Option<String>,
80 }
81
82 impl Display for Test {
83 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
84 let mut writer = QueryStringFormatter::new(f);
85 writer.write_opt_param("a", self.a.as_ref())?;
86 writer.write_opt_param("b", self.b.as_ref())
87 }
88 }
89
90 #[test]
91 fn test_query_string_formatter_filled() {
92 let test = Test {
93 a: Some(1),
94 b: Some("hello".to_string()),
95 };
96
97 assert_eq!(test.to_string(), "?a=1&b=hello");
98 }
99
100 #[test]
101 fn test_query_string_formatter_empty() {
102 let test = Test { a: None, b: None };
103
104 assert_eq!(test.to_string(), "");
105 }
106
107 #[test]
108 fn test_query_string_formatter_single() {
109 let test = Test {
110 a: Some(1),
111 b: None,
112 };
113
114 assert_eq!(test.to_string(), "?a=1");
115 }
116
117 #[test]
118 fn test_query_array() {
119 let query_array = QueryArray([1, 2, 3]);
120 assert_eq!(query_array.to_string(), "1,2,3");
121
122 let params = vec!["a", "b", "c"];
123 let query_array = QueryArray(¶ms);
124 assert_eq!(query_array.to_string(), "a,b,c");
125 }
126}