use std::fmt::Display;
use reqwest::Url;
use crate::query::{AsApiStr, join_api_values};
use crate::{Error, Result};
pub(crate) type QueryParam = (&'static str, String);
pub(crate) fn build_endpoint_url(
base: &Url,
base_field: &'static str,
path: &str,
api_key: Option<&str>,
params: Vec<QueryParam>,
) -> Result<Url> {
let base_query = base.query().map(str::to_owned);
let mut url = base.join(path).map_err(|err| Error::InvalidParam {
field: base_field,
reason: err.to_string(),
})?;
url.set_query(base_query.as_deref());
{
let mut pairs = url.query_pairs_mut();
for (field, value) in params {
pairs.append_pair(field, &value);
}
if let Some(api_key) = api_key {
pairs.append_pair("apikey", api_key);
}
}
Ok(url)
}
pub(crate) fn push_api_values<T>(params: &mut Vec<QueryParam>, field: &'static str, values: &[T])
where
T: AsApiStr,
{
if !values.is_empty() {
params.push((field, join_api_values(values)));
}
}
pub(crate) fn push_api_param<T>(
params: &mut Vec<QueryParam>,
field: &'static str,
value: Option<&T>,
) where
T: AsApiStr + ?Sized,
{
if let Some(value) = value {
params.push((field, value.as_api_str().into_owned()));
}
}
pub(crate) fn push_display_param<T>(
params: &mut Vec<QueryParam>,
field: &'static str,
value: Option<T>,
) where
T: Display,
{
if let Some(value) = value {
params.push((field, value.to_string()));
}
}
pub(crate) fn push_float_param(
params: &mut Vec<QueryParam>,
field: &'static str,
value: Option<f64>,
) {
if let Some(value) = value {
params.push((field, format_float_param(value)));
}
}
fn format_float_param(value: f64) -> String {
if value.is_nan() {
"nan".to_owned()
} else {
value.to_string()
}
}