#[derive(Debug, Clone, Default)]
pub struct Params(Vec<(String, String)>);
impl Params {
pub fn new() -> Self {
Params(Vec::new())
}
pub fn set(mut self, key: &str, value: impl QueryValue) -> Self {
if let Some(v) = value.to_query() {
self.0.retain(|(k, _)| k != key);
self.0.push((key.to_string(), v));
}
self
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub(crate) fn pairs(&self) -> &[(String, String)] {
&self.0
}
pub(crate) fn with_page(&self, page: u32) -> Params {
self.clone().set("page", page)
}
}
pub trait QueryValue {
fn to_query(&self) -> Option<String>;
}
impl QueryValue for &str {
fn to_query(&self) -> Option<String> {
Some((*self).to_string())
}
}
impl QueryValue for String {
fn to_query(&self) -> Option<String> {
Some(self.clone())
}
}
impl QueryValue for bool {
fn to_query(&self) -> Option<String> {
Some(if *self { "true" } else { "false" }.to_string())
}
}
macro_rules! query_value_display {
($($t:ty),*) => {
$(impl QueryValue for $t {
fn to_query(&self) -> Option<String> { Some(self.to_string()) }
})*
};
}
query_value_display!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64);
impl<T: QueryValue> QueryValue for Option<T> {
fn to_query(&self) -> Option<String> {
self.as_ref().and_then(QueryValue::to_query)
}
}
impl QueryValue for Vec<&str> {
fn to_query(&self) -> Option<String> {
if self.is_empty() {
None
} else {
Some(self.join(","))
}
}
}
impl QueryValue for Vec<String> {
fn to_query(&self) -> Option<String> {
if self.is_empty() {
None
} else {
Some(self.join(","))
}
}
}