use std::str::{self};
use rand::Rng;
use utcnow::utcnow;
use base64::{Engine as _, engine::general_purpose};
use crate::constants::*;
pub(crate) fn milliseconds_now() -> i64 {
let ts = utcnow().unwrap().as_millis();
let max = i64::MAX;
if ts <= max as i128 {
ts as i64
} else {
max
}
}
pub(crate) fn from_base_36(sample: &str) -> Option<Vec<u8>> {
if sample.len() > 0 {
base_encode::from_str(sample, 36, BASE_36_CHARS)
} else {
None
}
}
pub(crate) fn from_base_16(sample: &str) -> Option<Vec<u8>> {
base_encode::from_str(sample, 16, HEX_CHARS)
}
pub(crate) fn base_36_parts_to_hex_dec(sample: &str) -> Option<String> {
if let Some(values) = from_base_36(sample) {
base_encode::to_string(&values, 16, HEX_CHARS)
} else {
None
}
}
pub(crate) fn hex_dec_to_base_36(sample: &str) -> Option<String> {
if let Some(values) = from_base_16(sample) {
base_encode::to_string(&values, 36, BASE_36_CHARS)
} else {
None
}
}
pub(crate) fn dec_to_base_36(value: u32) -> Option<String> {
let buf = value.to_be_bytes();
base_encode::to_string(&buf, 36, BASE_36_CHARS)
}
pub(crate) fn i64_to_base_36(value: i64) -> Option<String> {
let buf = value.to_be_bytes();
base_encode::to_string(&buf, 36, BASE_36_CHARS)
}
pub(crate) fn base_36_to_u8(letter: &char) -> Option<u8> {
if let Some(values) = from_base_36(&letter.to_string()) {
if values.len() > 0 {
if let Some(value) = values.last() {
Some(*value)
} else {
None
}
} else {
None
}
} else {
None
}
}
pub(crate) fn base_36_str_to_u64(sample: &str) -> Option<u64> {
if let Some(values) = from_base_36(sample) {
let radix: u64 = 256;
let num_values = values.len();
let max_36_pow = 12;
if num_values > 0 {
let max_pow = if num_values < max_36_pow { values.len() - 1 } else { max_36_pow };
let mut curr_pow = max_pow as u32;
let mut sum: u64 = 0;
for v in values {
let multiplier = if curr_pow > 0 { radix.pow(curr_pow) } else { 1u64 };
sum += v as u64 * multiplier;
if curr_pow > 0 {
curr_pow -= 1;
}
}
Some(sum)
} else {
None
}
} else {
None
}
}
pub(crate) fn random_int(max: u32) -> u32 {
let mut rng = rand::thread_rng();
rng.gen::<u32>() % max
}
pub(crate) fn rand_char(characters: &[char]) -> char {
let len = characters.len();
let rand_index = random_int(len as u32) as usize;
characters.get(rand_index).unwrap_or(&' ').to_owned()
}
pub(crate) fn rand_char_as_string(rand_chars: &[char]) -> String{
rand_char(rand_chars).to_string()
}
pub(crate) fn rand_int_36(power: u8) -> String {
let max = 10u32.pow(power as u32);
let rand_int = random_int(max);
dec_to_base_36(rand_int).unwrap_or("".to_string())
}
pub(crate) fn hex_string_to_base36_parts(hex_str: &str) -> Option<String> {
if hex_str.len() >= MIN_VALID_UUID_LENGTH {
let base36_str = vec![&hex_str[..12],&hex_str[12..]].into_iter()
.map(|hd| hex_dec_to_base_36(hd).unwrap_or("".to_string()))
.collect::<Vec<String>>()
.join("_");
Some(base36_str)
} else {
None
}
}
pub fn encode_base64(key_str: &str) -> String {
general_purpose::STANDARD.encode(key_str)
}
pub fn decode_base64(sample: &str) -> String {
let decoded = general_purpose::STANDARD.decode(sample).unwrap_or(vec![]);
str::from_utf8(&decoded).unwrap_or("").to_string()
}