1#[derive(Debug, Clone, Default)]
9pub struct Params(Vec<(String, String)>);
10
11impl Params {
12 pub fn new() -> Self {
13 Params(Vec::new())
14 }
15
16 pub fn set(mut self, key: &str, value: impl QueryValue) -> Self {
19 if let Some(v) = value.to_query() {
20 self.0.retain(|(k, _)| k != key);
21 self.0.push((key.to_string(), v));
22 }
23 self
24 }
25
26 pub fn is_empty(&self) -> bool {
27 self.0.is_empty()
28 }
29
30 pub(crate) fn pairs(&self) -> &[(String, String)] {
31 &self.0
32 }
33
34 pub(crate) fn with_page(&self, page: u32) -> Params {
35 self.clone().set("page", page)
36 }
37}
38
39pub trait QueryValue {
41 fn to_query(&self) -> Option<String>;
42}
43
44impl QueryValue for &str {
45 fn to_query(&self) -> Option<String> {
46 Some((*self).to_string())
47 }
48}
49
50impl QueryValue for String {
51 fn to_query(&self) -> Option<String> {
52 Some(self.clone())
53 }
54}
55
56impl QueryValue for bool {
57 fn to_query(&self) -> Option<String> {
58 Some(if *self { "true" } else { "false" }.to_string())
59 }
60}
61
62macro_rules! query_value_display {
63 ($($t:ty),*) => {
64 $(impl QueryValue for $t {
65 fn to_query(&self) -> Option<String> { Some(self.to_string()) }
66 })*
67 };
68}
69query_value_display!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64);
70
71impl<T: QueryValue> QueryValue for Option<T> {
72 fn to_query(&self) -> Option<String> {
73 self.as_ref().and_then(QueryValue::to_query)
74 }
75}
76
77impl QueryValue for Vec<&str> {
78 fn to_query(&self) -> Option<String> {
79 if self.is_empty() {
80 None
81 } else {
82 Some(self.join(","))
83 }
84 }
85}
86
87impl QueryValue for Vec<String> {
88 fn to_query(&self) -> Option<String> {
89 if self.is_empty() {
90 None
91 } else {
92 Some(self.join(","))
93 }
94 }
95}