use std::io::Write;
use std::process;
use std::time::SystemTime;
use byteorder::{BigEndian, WriteBytesExt};
use once_cell::sync::Lazy;
use parking_lot::Mutex;
use time::{Date, OffsetDateTime, PrimitiveDateTime, Time};
pub(crate) static UNIQ_ID_GENERATOR: Lazy<Mutex<UniqueIdGenerator>> = Lazy::new(|| {
let mut wtr = Vec::new();
wtr.write_u8(1).unwrap();
let x = mac_address::get_mac_address().unwrap();
let ma = match x {
Some(ma) => ma,
None => {
panic!("mac address is none")
}
};
wtr.write_all(&ma.bytes()).unwrap();
wtr.write_u16::<BigEndian>(process::id() as u16).unwrap();
let generator = UniqueIdGenerator {
counter: 0,
start_timestamp: 0,
next_timestamp: 0,
prefix: hex::encode_upper(wtr),
};
Mutex::new(generator)
});
pub(crate) struct UniqueIdGenerator {
counter: i32,
prefix: String,
start_timestamp: i64,
next_timestamp: i64,
}
impl UniqueIdGenerator {
pub fn next_id(&mut self) -> String {
if SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs() as i64
> self.next_timestamp
{
let now = OffsetDateTime::now_utc();
let year = now.year();
let month = now.month();
self.start_timestamp = PrimitiveDateTime::new(
Date::from_calendar_date(year, month, 1).unwrap(),
Time::from_hms(0, 0, 0).unwrap(),
)
.assume_offset(now.offset())
.unix_timestamp();
self.next_timestamp = (PrimitiveDateTime::new(
Date::from_calendar_date(year, month, 1).unwrap(),
Time::from_hms(0, 0, 0).unwrap(),
)
.assume_offset(now.offset())
+ time::Duration::days(30))
.unix_timestamp();
}
self.counter = self.counter.wrapping_add(1);
let mut buf = Vec::new();
buf.write_i32::<BigEndian>(
((OffsetDateTime::now_utc().unix_timestamp() - self.start_timestamp) * 1000) as i32,
)
.unwrap();
buf.write_i32::<BigEndian>(self.counter).unwrap();
self.prefix.clone() + &hex::encode(buf)
}
}
#[cfg(test)]
mod test {
#[ignore]
#[test]
fn generate_uniq_id() {
use super::UNIQ_ID_GENERATOR;
for i in 1..17 {
let uid = UNIQ_ID_GENERATOR.lock().next_id();
assert_eq!(uid.len(), 34);
assert_eq!(uid.get(26..).unwrap(), hex::encode(vec![0, 0, 0, i as u8]));
}
}
}