use std::ops::{Deref, DerefMut};
use url::{form_urlencoded, Url};
pub(crate) fn remove_query_params(url: &Url, params: &[&str]) -> Url {
let mut stripped = url.clone();
match url.query() {
None => stripped,
Some(query) => {
let kept: Vec<&str> = query
.split('&')
.filter(|segment| !segment.is_empty())
.filter(|segment| {
let raw_key = segment.split('=').next().unwrap_or_default();
let key = form_urlencoded::parse(raw_key.as_bytes())
.next()
.map(|(key, _)| key)
.unwrap_or_default();
!params.contains(&&*key)
})
.collect();
let query = kept.join("&");
stripped.set_query(match query.is_empty() {
true => None,
false => Some(&query),
});
stripped
}
}
}
pub struct DummyBox<T>(pub T);
impl<T> Deref for DummyBox<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for DummyBox<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[cfg(feature = "dst_arrow")]
pub fn decimal_to_i128(mut v: rust_decimal::Decimal, scale: u32) -> anyhow::Result<i128> {
v.rescale(scale);
let v_scale = v.scale();
if v_scale != scale as u32 {
return Err(anyhow::anyhow!(
"decimal scale is not equal to expected scale, got: {} expected: {}",
v_scale,
scale
));
}
Ok(v.mantissa())
}
#[cfg(test)]
mod tests {
use super::remove_query_params;
use url::Url;
fn strip(uri: &str, params: &[&str]) -> String {
remove_query_params(&Url::parse(uri).unwrap(), params).to_string()
}
#[test]
fn preserves_spaces_in_values() {
assert_eq!(
strip(
"postgresql://u:p@host/db?options=-c%20statement_timeout%3D1s&cxprotocol=binary",
&["cxprotocol"]
),
"postgresql://u:p@host/db?options=-c%20statement_timeout%3D1s"
);
}
#[test]
fn does_not_reencode_remaining_params() {
assert_eq!(
strip("mysql://host/db?a=x+y&b=%2Fz&flag", &["nothing"]),
"mysql://host/db?a=x+y&b=%2Fz&flag"
);
}
#[test]
fn removes_every_requested_param() {
assert_eq!(
strip(
"postgresql://host/db?sslcert=a&keep=1&sslkey=b&sslrootcert=c",
&["sslcert", "sslkey", "sslrootcert"]
),
"postgresql://host/db?keep=1"
);
}
#[test]
fn drops_the_query_when_nothing_is_left() {
assert_eq!(
strip("postgresql://host/db?cxprotocol=binary", &["cxprotocol"]),
"postgresql://host/db"
);
}
#[test]
fn handles_a_missing_query() {
assert_eq!(
strip("postgresql://host/db", &["cxprotocol"]),
"postgresql://host/db"
);
}
#[test]
fn matches_percent_encoded_keys() {
assert_eq!(
strip(
"postgresql://host/db?cx%70rotocol=binary&a=1",
&["cxprotocol"]
),
"postgresql://host/db?a=1"
);
}
#[test]
fn keeps_duplicate_keys_that_are_not_removed() {
assert_eq!(
strip("mysql://host/db?a=1&a=2&cxprotocol=text", &["cxprotocol"]),
"mysql://host/db?a=1&a=2"
);
}
}