#[cfg(feature = "puuid")]
use base64::alphabet::URL_SAFE;
#[cfg(feature = "puuid")]
use base64::engine::{GeneralPurpose, GeneralPurposeConfig};
#[cfg(feature = "puuid")]
use base64::Engine;
#[cfg(feature = "puuid")]
use serde::de::DeserializeOwned;
use serde::de::Error;
use serde::{Deserialize, Deserializer, Serializer};
use std::fmt::Display;
use time::OffsetDateTime;
use url::Url;
pub(crate) fn set_query_args<K: Display, V: Display>(
url: &mut Url,
query_args: impl Iterator<Item = (K, V)>,
) {
let mut args = url.query_pairs_mut();
query_args.into_iter().for_each(|(key, value)| {
args.append_pair(format!("{}", key).as_str(), format!("{}", value).as_str());
});
}
pub(crate) fn de_milliseconds<'de, D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
where
D: Deserializer<'de>,
{
let millis: i64 = Deserialize::deserialize(deserializer)?;
OffsetDateTime::from_unix_timestamp(millis / 1000).map_err(Error::custom)
}
pub(crate) fn se_milliseconds<S>(x: &OffsetDateTime, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
s.serialize_i64(x.unix_timestamp())
}
#[cfg(feature = "puuid")]
#[derive(Debug)]
pub enum DecodeJWTError {
Decode(base64::DecodeError),
InvalidBase64,
Parse(serde_json::Error),
}
#[cfg(feature = "puuid")]
impl Display for DecodeJWTError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DecodeJWTError::Decode(e) => write!(f, "Decode error: {}", e),
DecodeJWTError::InvalidBase64 => write!(f, "Invalid base64"),
DecodeJWTError::Parse(e) => write!(f, "Parse error: {}", e),
}
}
}
#[cfg(feature = "puuid")]
pub(crate) fn decode_jwt<T: DeserializeOwned>(result: &str) -> Result<T, DecodeJWTError> {
let parts: Vec<&str> = result.split('.').collect();
let base64 = parts.get(1).ok_or(DecodeJWTError::InvalidBase64)?;
let base64 = base64.replace('-', "+").replace('_', "/");
let decoded = GeneralPurpose::new(&URL_SAFE, GeneralPurposeConfig::new())
.decode(base64.as_bytes())
.map_err(DecodeJWTError::Decode)?;
serde_json::from_slice(&decoded).map_err(DecodeJWTError::Parse)
}