1use rand::Rng;
2use chrono::{DateTime, TimeZone, Utc};
3use std::num::ParseIntError;
4
5pub fn get_noise() -> String {
6 let mut rng = rand::thread_rng();
7 let counter: u16 = rng.gen_range(0..=u16::MAX);
8 format!("{:02x}", counter)
9}
10
11pub fn parse_aid(aid: &str) -> Result<DateTime<Utc>, Box<dyn std::error::Error>> {
12 let base36_time = &aid[..8];
13 let time_milliseconds = b36_decode(base36_time)?;
14 let timestamp = 946684800 + time_milliseconds / 1000;
15 Utc.timestamp_opt(timestamp as i64, 0)
16 .single()
17 .ok_or_else(|| "Invalid timestamp".into())
18}
19
20pub fn gen_aid() -> String {
21 let current = ((chrono::Utc::now().timestamp() + 946684800) * 1000) as u64;
22 let base36_time = b36_encode(current);
23 let noise = get_noise();
24 format!("{:0>8}{}", base36_time, noise)
25}
26
27pub fn gen_aidx() -> String {
28 let current_time = ((chrono::Utc::now().timestamp() + 946684800) * 1000) as u64;
29 let base36_time = b36_encode(current_time);
30 let individual_id = format!("{:04X}", rand::thread_rng().gen_range(0..=u16::MAX));
31 let counter = format!("{:04X}", rand::thread_rng().gen_range(0..=u16::MAX));
32 format!("{:0>8}{}{}", base36_time, individual_id, counter)
33}
34
35pub fn parse_aidx(aidx: &str) -> Result<DateTime<Utc>, Box<dyn std::error::Error>> {
36 let base36_time = &aidx[..8];
37 let time_milliseconds = b36_decode(base36_time)?;
38 let timestamp = 946684800 + time_milliseconds / 1000;
39 Utc.timestamp_opt(timestamp as i64, 0)
40 .single()
41 .ok_or_else(|| "Invalid timestamp".into())
42}
43
44fn b36_encode(mut number: u64) -> String {
45 let alphabet = "0123456789abcdefghijklmnopqrstuvwxyz";
46 let mut base36 = String::new();
47 while number > 0 {
48 let (quotient, remainder) = (number / 36, number % 36);
49 base36.insert(0, alphabet.chars().nth(remainder as usize).unwrap());
50 number = quotient;
51 }
52 if base36.is_empty() {
53 base36.push(alphabet.chars().nth(0).unwrap());
54 }
55 base36
56}
57
58fn b36_decode(number: &str) -> Result<u64, ParseIntError> {
59 u64::from_str_radix(number, 36)
60}