autopush_common/util/
mod.rs1use std::collections::HashMap;
3use std::hash::Hash;
4use std::time::Duration;
5
6use base64::Engine;
7use serde::{Deserialize, Deserializer};
8
9pub mod timing;
10pub mod user_agent;
11
12pub use self::timing::{ms_since_epoch, ms_utc_midnight, sec_since_epoch, us_since_epoch};
13
14pub trait InsertOpt<K: Eq + Hash, V> {
15 fn insert_opt(&mut self, key: impl Into<K>, value: Option<impl Into<V>>);
17}
18
19impl<K: Eq + Hash, V> InsertOpt<K, V> for HashMap<K, V> {
20 fn insert_opt(&mut self, key: impl Into<K>, value: Option<impl Into<V>>) {
21 if let Some(value) = value {
22 self.insert(key.into(), value.into());
23 }
24 }
25}
26
27pub fn b64_decode_url(input: &str) -> Result<Vec<u8>, base64::DecodeError> {
31 base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(input.trim_end_matches('='))
32}
33
34pub fn b64_encode_url(input: &Vec<u8>) -> String {
35 base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(input)
36}
37
38pub fn b64_decode_std(input: &str) -> Result<Vec<u8>, base64::DecodeError> {
39 base64::engine::general_purpose::STANDARD_NO_PAD.decode(input.trim_end_matches('='))
40}
41
42pub fn b64_encode_std(input: &Vec<u8>) -> String {
43 base64::engine::general_purpose::STANDARD_NO_PAD.encode(input)
44}
45
46pub fn b64_decode(input: &str) -> Result<Vec<u8>, base64::DecodeError> {
48 b64_decode_url(input).or_else(|_| b64_decode_std(input))
49}
50
51pub fn deserialize_u32_to_duration<'de, D>(deserializer: D) -> Result<Duration, D::Error>
52where
53 D: Deserializer<'de>,
54{
55 let seconds: u32 = Deserialize::deserialize(deserializer)?;
56 Ok(Duration::from_secs(seconds.into()))
57}
58
59pub fn deserialize_opt_u32_to_duration<'de, D>(
60 deserializer: D,
61) -> Result<Option<Duration>, D::Error>
62where
63 D: Deserializer<'de>,
64{
65 let seconds: Option<u32> = Deserialize::deserialize(deserializer)?;
66 Ok(seconds.map(|v| Duration::from_secs(v.into())))
67}