use crate::error::DatError;
use base64::engine::general_purpose;
use base64::Engine;
use std::time::SystemTime;
const BASE64_URL: &general_purpose::GeneralPurpose = &general_purpose::URL_SAFE_NO_PAD;
const HEX_BYTES: &[u8; 16] = b"0123456789abcdef";
pub fn encode_base64_url<T: AsRef<[u8]>>(b: T) -> String {
BASE64_URL.encode(b)
}
pub fn encode_base64_url_out<T: AsRef<[u8]>>(b: T, out: &mut String) {
BASE64_URL.encode_string(b, out)
}
pub fn decode_base64_url<T: AsRef<[u8]>>(b64: T) -> Result<Vec<u8>, DatError> {
BASE64_URL.decode(&b64).map_err(|_| DatError::InvalidBase64Format)
}
pub fn decode_base64_url_out<T: AsRef<[u8]>>(b64: T, out: &mut Vec<u8>) -> Result<(), DatError> {
BASE64_URL.decode_vec(&b64, out).map_err(|_| DatError::InvalidBase64Format)
}
pub fn decode_base64_url_out_str<T: AsRef<[u8]>>(b64: T, out: &mut String) -> Result<(), DatError> {
unsafe {
BASE64_URL.decode_vec(&b64, out.as_mut_vec()).map_err(|_| DatError::InvalidBase64Format)
}
}
pub fn now_unix_timestamp() -> u64 {
SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs()
}
pub fn to_utf8(vec: Vec<u8>) -> Result<String, DatError> {
String::from_utf8(vec).map_err(|_| DatError::Utf8EncodeError)
}
#[inline(always)]
pub fn to_hex_from_u64_out(n: u64, out: &mut String) {
if n == 0 {
out.push('0');
return;
}
let bits_needed = 64 - n.leading_zeros();
let len = ((bits_needed + 3) / 4) as usize;
unsafe {
let vec = out.as_mut_vec();
let old_len = vec.len();
vec.reserve(len);
vec.set_len(old_len + len);
let dest = &mut vec[old_len..];
let mut temp_n = n;
for i in (0..len).rev() {
dest[i] = HEX_BYTES[(temp_n & 0xf) as usize];
temp_n >>= 4;
}
}
}