alchemy_api/cores/
params.rs

1use std::borrow::Cow;
2use url::Url;
3
4/// A trait representing a parameter value.
5pub trait ParamValue<'a> {
6    /// The parameter value as a string.
7    fn as_value(&self) -> Cow<'a, str>;
8}
9
10impl ParamValue<'static> for bool {
11    fn as_value(&self) -> Cow<'static, str> {
12        if *self {
13            "true".into()
14        } else {
15            "false".into()
16        }
17    }
18}
19
20impl<'a> ParamValue<'a> for &'a str {
21    fn as_value(&self) -> Cow<'a, str> {
22        (*self).into()
23    }
24}
25
26impl ParamValue<'static> for String {
27    fn as_value(&self) -> Cow<'static, str> {
28        self.clone().into()
29    }
30}
31
32impl<'a> ParamValue<'a> for &'a String {
33    fn as_value(&self) -> Cow<'a, str> {
34        (*self).into()
35    }
36}
37
38impl<'a> ParamValue<'a> for Cow<'a, str> {
39    fn as_value(&self) -> Cow<'a, str> {
40        self.clone()
41    }
42}
43
44impl<'a, 'b: 'a> ParamValue<'a> for &'b Cow<'a, str> {
45    fn as_value(&self) -> Cow<'a, str> {
46        (*self).clone()
47    }
48}
49
50impl ParamValue<'static> for u64 {
51    fn as_value(&self) -> Cow<'static, str> {
52        self.to_string().into()
53    }
54}
55
56impl ParamValue<'static> for f64 {
57    fn as_value(&self) -> Cow<'static, str> {
58        self.to_string().into()
59    }
60}
61
62/// A structure for form parameters.
63#[derive(Debug, Default, Clone)]
64pub struct FormParams<'a> {
65    params: Vec<(Cow<'a, str>, Cow<'a, str>)>,
66}
67
68impl<'a> FormParams<'a> {
69    /// Push a single parameter.
70    pub fn push<'b, K, V>(&mut self, key: K, value: V) -> &mut Self
71    where
72        K: Into<Cow<'a, str>>,
73        V: ParamValue<'b>,
74        'b: 'a,
75    {
76        self.params.push((key.into(), value.as_value()));
77        self
78    }
79
80    /// Push a single parameter.
81    pub fn push_opt<'b, K, V>(&mut self, key: K, value: Option<V>) -> &mut Self
82    where
83        K: Into<Cow<'a, str>>,
84        V: ParamValue<'b>,
85        'b: 'a,
86    {
87        if let Some(value) = value {
88            self.params.push((key.into(), value.as_value()));
89        }
90        self
91    }
92
93    /// Push a set of parameters.
94    pub fn extend<'b, I, K, V>(&mut self, iter: I) -> &mut Self
95    where
96        I: Iterator<Item = (K, V)>,
97        K: Into<Cow<'a, str>>,
98        V: ParamValue<'b>,
99        'b: 'a,
100    {
101        self.params
102            .extend(iter.map(|(key, value)| (key.into(), value.as_value())));
103        self
104    }
105
106    /// Encode the parameters into a request body.
107    pub fn into_body(self) -> anyhow::Result<Option<(&'static str, Vec<u8>)>> {
108        let body = serde_urlencoded::to_string(self.params)?;
109        Ok(Some((
110            "application/x-www-form-urlencoded",
111            body.into_bytes(),
112        )))
113    }
114}
115
116/// A structure for query parameters.
117#[derive(Debug, Default, Clone)]
118pub struct QueryParams<'a> {
119    params: Vec<(Cow<'a, str>, Cow<'a, str>)>,
120}
121
122impl<'a> QueryParams<'a> {
123    /// Push a single parameter.
124    pub fn push<'b, K, V>(&mut self, key: K, value: V) -> &mut Self
125    where
126        K: Into<Cow<'a, str>>,
127        V: ParamValue<'b>,
128        'b: 'a,
129    {
130        self.params.push((key.into(), value.as_value()));
131        self
132    }
133
134    /// Push a single parameter.
135    pub fn push_opt<'b, K, V>(&mut self, key: K, value: Option<V>) -> &mut Self
136    where
137        K: Into<Cow<'a, str>>,
138        V: ParamValue<'b>,
139        'b: 'a,
140    {
141        if let Some(value) = value {
142            self.params.push((key.into(), value.as_value()));
143        }
144        self
145    }
146
147    /// Push a set of parameters.
148    pub fn extend<'b, I, K, V>(&mut self, iter: I) -> &mut Self
149    where
150        I: Iterator<Item = (K, V)>,
151        K: Into<Cow<'a, str>>,
152        V: ParamValue<'b>,
153        'b: 'a,
154    {
155        self.params
156            .extend(iter.map(|(key, value)| (key.into(), value.as_value())));
157        self
158    }
159
160    /// Add the parameters to a URL.
161    pub fn add_to_url(&self, url: &mut Url) {
162        let mut pairs = url.query_pairs_mut();
163        pairs.extend_pairs(self.params.iter());
164    }
165}